From 5724c9611a88a16d2aa42c7c69254e8adc492c8b Mon Sep 17 00:00:00 2001 From: Roman Telezhynskyi Date: Tue, 28 Nov 2023 16:40:27 +0200 Subject: [PATCH] New feature. Boundary together with notches. --- ChangeLog.txt | 1 + dist/OBS_debian/debian.valentina.1 | 4 +- dist/debian/valentina.1 | 4 +- src/app/puzzle/carousel/vpcarrousel.cpp | 6 + src/app/puzzle/carousel/vpcarrousel.h | 2 + src/app/puzzle/carousel/vpcarrouselpiece.cpp | 10 +- src/app/puzzle/layout/vplayout.h | 1 + src/app/puzzle/layout/vplayoutsettings.cpp | 22 +- src/app/puzzle/layout/vplayoutsettings.h | 32 +- src/app/puzzle/layout/vpsheet.cpp | 2 + src/app/puzzle/scene/vpgraphicspiece.cpp | 127 +++- src/app/puzzle/vpmainwindow.cpp | 36 + src/app/puzzle/vpmainwindow.h | 2 + src/app/puzzle/vpmainwindow.ui | 11 +- src/app/puzzle/xml/vplayoutfilereader.cpp | 2 + src/app/puzzle/xml/vplayoutfilewriter.cpp | 1 + src/app/puzzle/xml/vplayoutliterals.cpp | 107 +-- src/app/puzzle/xml/vplayoutliterals.h | 1 + src/app/valentina/core/vcmdexport.cpp | 3 + .../dialogs/dialoglayoutsettings.cpp | 29 + .../valentina/dialogs/dialoglayoutsettings.h | 19 +- .../valentina/dialogs/dialoglayoutsettings.ui | 23 + .../valentina/dialogs/dialogsavelayout.cpp | 18 + src/app/valentina/dialogs/dialogsavelayout.h | 14 +- src/app/valentina/dialogs/dialogsavelayout.ui | 17 +- src/app/valentina/mainwindow.cpp | 39 +- src/app/valentina/mainwindow.h | 1 + src/app/valentina/mainwindow.ui | 12 + src/app/valentina/mainwindowsnogui.cpp | 19 +- src/app/valentina/xml/vpattern.cpp | 3 +- src/libs/ifc/schema.qrc | 1 + src/libs/ifc/schema/layout/v0.1.7.xsd | 590 ++++++++++++++++ src/libs/ifc/xml/vlayoutconverter.cpp | 20 +- src/libs/ifc/xml/vlayoutconverter.h | 4 +- src/libs/vdxf/vdxfengine.cpp | 165 ++++- src/libs/vdxf/vdxfengine.h | 5 + src/libs/vdxf/vdxfpaintdevice.cpp | 18 + src/libs/vdxf/vdxfpaintdevice.h | 3 + src/libs/vgeometry/vabstractcurve.cpp | 68 -- src/libs/vgeometry/vabstractcurve.h | 3 - src/libs/vgeometry/vgeometrydef.cpp | 9 +- src/libs/vgeometry/vgeometrydef.h | 18 +- src/libs/vhpgl/vhpglengine.cpp | 182 ++--- src/libs/vhpgl/vhpglengine.h | 19 +- src/libs/vhpgl/vhpglpaintdevice.cpp | 18 + src/libs/vhpgl/vhpglpaintdevice.h | 3 + src/libs/vlayout/vabstractpiece.cpp | 4 +- src/libs/vlayout/vabstractpiece.h | 3 +- src/libs/vlayout/vbank.cpp | 54 +- src/libs/vlayout/vbank.h | 14 +- src/libs/vlayout/vboundary.cpp | 644 ++++++++++++++++++ src/libs/vlayout/vboundary.h | 85 +++ src/libs/vlayout/vlayout.pri | 6 +- src/libs/vlayout/vlayout.qbs | 4 +- src/libs/vlayout/vlayoutexporter.cpp | 4 + src/libs/vlayout/vlayoutexporter.h | 16 + src/libs/vlayout/vlayoutgenerator.cpp | 64 +- src/libs/vlayout/vlayoutgenerator.h | 74 +- src/libs/vlayout/vlayoutpaper.cpp | 10 +- src/libs/vlayout/vlayoutpaper.h | 6 +- src/libs/vlayout/vlayoutpiece.cpp | 366 ++++++---- src/libs/vlayout/vlayoutpiece.h | 16 +- src/libs/vlayout/vprintlayout.h | 76 ++- src/libs/vmisc/commandoptions.cpp | 4 +- src/libs/vmisc/commandoptions.h | 1 + src/libs/vmisc/vvalentinasettings.cpp | 36 + src/libs/vmisc/vvalentinasettings.h | 7 + src/libs/vpatterndb/vpassmark.cpp | 4 +- src/libs/vpatterndb/vpassmark.h | 46 +- src/libs/vpatterndb/vpiece.cpp | 4 +- src/libs/vtools/tools/vtoolseamallowance.cpp | 107 ++- .../vtools/undocommands/label/movelabel.cpp | 13 +- 72 files changed, 2670 insertions(+), 692 deletions(-) create mode 100644 src/libs/ifc/schema/layout/v0.1.7.xsd create mode 100644 src/libs/vlayout/vboundary.cpp create mode 100644 src/libs/vlayout/vboundary.h diff --git a/ChangeLog.txt b/ChangeLog.txt index 25f5b2ba4..99eeff106 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -58,6 +58,7 @@ - Adding removing nodes of curved path. - New tools: Arc start point, Arc end point. - Optimize U-notch shape. +- New feature. Boundary together with notches. # Valentina 0.7.52 September 12, 2022 - Fix crash when default locale is ru. diff --git a/dist/OBS_debian/debian.valentina.1 b/dist/OBS_debian/debian.valentina.1 index da77d4adf..a8c31c902 100644 --- a/dist/OBS_debian/debian.valentina.1 +++ b/dist/OBS_debian/debian.valentina.1 @@ -1,6 +1,6 @@ .\" Manpage for valentina. .\" Contact dismine@gmail.com to correct errors. -.TH valentina 1 "July 10, 2023" "valentina man page" +.TH valentina 1 "28 November, 2023" "valentina man page" .SH NAME Valentina \- Pattern making program. .SH SYNOPSIS @@ -199,6 +199,8 @@ The path to output destination folder. By default the directory at which the app .RB "Unite pages if possible (" "export mode" "). Maximum value limited by QImage that supports only a maximum of " "32768x32768 px" " images." .IP "--preferOneSheetSolution" .RB "Prefer one sheet layout solution (" "export mode" ")." +.IP "--boundaryTogetherWithNotches" +.RB "Export boundary together with notches (" "export mode" ")." .IP "-S, --savelen" .RB "Save length of the sheet if set (" "export mode" "). The option tells the program to use as much as possible width of sheet. Quality of a layout can be worse when this option was used." .IP "-l, --layounits " diff --git a/dist/debian/valentina.1 b/dist/debian/valentina.1 index da77d4adf..a8c31c902 100755 --- a/dist/debian/valentina.1 +++ b/dist/debian/valentina.1 @@ -1,6 +1,6 @@ .\" Manpage for valentina. .\" Contact dismine@gmail.com to correct errors. -.TH valentina 1 "July 10, 2023" "valentina man page" +.TH valentina 1 "28 November, 2023" "valentina man page" .SH NAME Valentina \- Pattern making program. .SH SYNOPSIS @@ -199,6 +199,8 @@ The path to output destination folder. By default the directory at which the app .RB "Unite pages if possible (" "export mode" "). Maximum value limited by QImage that supports only a maximum of " "32768x32768 px" " images." .IP "--preferOneSheetSolution" .RB "Prefer one sheet layout solution (" "export mode" ")." +.IP "--boundaryTogetherWithNotches" +.RB "Export boundary together with notches (" "export mode" ")." .IP "-S, --savelen" .RB "Save length of the sheet if set (" "export mode" "). The option tells the program to use as much as possible width of sheet. Quality of a layout can be worse when this option was used." .IP "-l, --layounits " diff --git a/src/app/puzzle/carousel/vpcarrousel.cpp b/src/app/puzzle/carousel/vpcarrousel.cpp index 8b9317cdb..73f45003b 100644 --- a/src/app/puzzle/carousel/vpcarrousel.cpp +++ b/src/app/puzzle/carousel/vpcarrousel.cpp @@ -259,6 +259,12 @@ void VPCarrousel::SetOrientation(Qt::Orientation orientation) RefreshOrientation(); } +//--------------------------------------------------------------------------------------------------------------------- +void VPCarrousel::RefreshPieceMiniature() +{ + ui->listWidget->Refresh(); +} + //--------------------------------------------------------------------------------------------------------------------- void VPCarrousel::RefreshOrientation() { diff --git a/src/app/puzzle/carousel/vpcarrousel.h b/src/app/puzzle/carousel/vpcarrousel.h index 46934c470..4eb8b67bf 100644 --- a/src/app/puzzle/carousel/vpcarrousel.h +++ b/src/app/puzzle/carousel/vpcarrousel.h @@ -68,6 +68,8 @@ public: */ void SetOrientation(Qt::Orientation orientation); + void RefreshPieceMiniature(); + /** * @brief RefreshOrientation Refreshes the orientation of the carrousel with the * m_orientation value; diff --git a/src/app/puzzle/carousel/vpcarrouselpiece.cpp b/src/app/puzzle/carousel/vpcarrouselpiece.cpp index cc4261edf..f696e7bc9 100644 --- a/src/app/puzzle/carousel/vpcarrouselpiece.cpp +++ b/src/app/puzzle/carousel/vpcarrouselpiece.cpp @@ -32,6 +32,7 @@ #include #include +#include "../layout/vplayout.h" #include "../layout/vppiece.h" #include "../vmisc/theme/vscenestylesheet.h" @@ -139,7 +140,14 @@ auto VPCarrouselPiece::CreatePieceIcon(const QSize &size, bool isDragIcon) const painter.setBrush(QBrush(iconMode == QIcon::Selected ? style.CarrouselPieceSelectedColor() : style.CarrouselPieceForegroundColor())); - piece->DrawMiniature(painter); + bool togetherWithNotches = false; + VPLayoutPtr pieceLayout = piece->Layout(); + if (not pieceLayout.isNull()) + { + togetherWithNotches = pieceLayout->LayoutSettings().IsBoundaryTogetherWithNotches(); + } + + piece->DrawMiniature(painter, togetherWithNotches); painter.end(); diff --git a/src/app/puzzle/layout/vplayout.h b/src/app/puzzle/layout/vplayout.h index a87ec8123..1f3f70ca9 100644 --- a/src/app/puzzle/layout/vplayout.h +++ b/src/app/puzzle/layout/vplayout.h @@ -106,6 +106,7 @@ signals: void PieceSheetChanged(const VPPiecePtr &piece); void ActiveSheetChanged(const VPSheetPtr &focusedSheet); void PieceTransformationChanged(const VPPiecePtr &piece); + void BoundaryTogetherWithNotchesChanged(const VPPiecePtr &piece); void PieceZValueChanged(const VPPiecePtr &piece); void TransformationOriginChanged(); void SheetListChanged(); diff --git a/src/app/puzzle/layout/vplayoutsettings.cpp b/src/app/puzzle/layout/vplayoutsettings.cpp index a9cde29c6..eed348d09 100644 --- a/src/app/puzzle/layout/vplayoutsettings.cpp +++ b/src/app/puzzle/layout/vplayoutsettings.cpp @@ -113,10 +113,8 @@ void VPLayoutSettings::SetTilesSize(const QSizeF &size) //--------------------------------------------------------------------------------------------------------------------- void VPLayoutSettings::SetTilesSizeConverted(const QSizeF &size) { - m_tilesSize = QSizeF( - UnitConvertor(size.width(), GetUnit(), Unit::Px), - UnitConvertor(size.height(), GetUnit(), Unit::Px) - ); + m_tilesSize = + QSizeF(UnitConvertor(size.width(), GetUnit(), Unit::Px), UnitConvertor(size.height(), GetUnit(), Unit::Px)); } //--------------------------------------------------------------------------------------------------------------------- @@ -134,8 +132,7 @@ auto VPLayoutSettings::GetTilesSize() const -> QSizeF //--------------------------------------------------------------------------------------------------------------------- auto VPLayoutSettings::GetTilesSize(Unit unit) const -> QSizeF { - return {UnitConvertor(m_tilesSize.width(), Unit::Px, unit), - UnitConvertor(m_tilesSize.height(), Unit::Px, unit)}; + return {UnitConvertor(m_tilesSize.width(), Unit::Px, unit), UnitConvertor(m_tilesSize.height(), Unit::Px, unit)}; } //--------------------------------------------------------------------------------------------------------------------- @@ -240,7 +237,6 @@ auto VPLayoutSettings::GetPiecesGapConverted() const -> qreal return UnitConvertor(m_piecesGap, Unit::Px, m_unit); } - //--------------------------------------------------------------------------------------------------------------------- void VPLayoutSettings::SetStickyEdges(bool state) { @@ -396,3 +392,15 @@ void VPLayoutSettings::SetShowTileNumber(bool newTileNumbers) { m_showTileNumbers = newTileNumbers; } + +//--------------------------------------------------------------------------------------------------------------------- +void VPLayoutSettings::SetBoundaryTogetherWithNotches(bool value) +{ + m_togetherWithNotches = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VPLayoutSettings::IsBoundaryTogetherWithNotches() const -> bool +{ + return m_togetherWithNotches; +} diff --git a/src/app/puzzle/layout/vplayoutsettings.h b/src/app/puzzle/layout/vplayoutsettings.h index 60f0d9d45..7b2bac8c5 100644 --- a/src/app/puzzle/layout/vplayoutsettings.h +++ b/src/app/puzzle/layout/vplayoutsettings.h @@ -28,16 +28,17 @@ #ifndef VPLAYOUTSETTINGS_H #define VPLAYOUTSETTINGS_H +#include #include #include #include -#include #include "../vmisc/def.h" class VPLayoutSettings { Q_DECLARE_TR_FUNCTIONS(VPLayoutSettings) // NOLINT + public: VPLayoutSettings() = default; @@ -248,15 +249,15 @@ public: void SetShowGrid(bool value); /** - * @brief GetGridColWidth returns the placement grid column width in Unit::Px - * @return the placement grid column width in Unit::Px - */ + * @brief GetGridColWidth returns the placement grid column width in Unit::Px + * @return the placement grid column width in Unit::Px + */ auto GetGridColWidth() const -> qreal; /** - * @brief GetGridColWidth returns the placement grid column width in the layout's unit - * @return the placement grid column width in the layout's unit - */ + * @brief GetGridColWidth returns the placement grid column width in the layout's unit + * @return the placement grid column width in the layout's unit + */ auto GetGridColWidthConverted() const -> qreal; /** @@ -273,15 +274,15 @@ public: void SetGridColWidthConverted(qreal value); /** - * @brief GetGridRowHeight returns the placement grid row height in Unit::Px - * @return the placement grid row height in Unit::Px - */ + * @brief GetGridRowHeight returns the placement grid row height in Unit::Px + * @return the placement grid row height in Unit::Px + */ auto GetGridRowHeight() const -> qreal; /** - * @brief GetGridRowHeightConverted returns the placement grid row height in the layout's unit - * @return the placement grid row height in the layout's unit - */ + * @brief GetGridRowHeightConverted returns the placement grid row height in the layout's unit + * @return the placement grid row height in the layout's unit + */ auto GetGridRowHeightConverted() const -> qreal; /** @@ -318,6 +319,9 @@ public: auto GetShowTileNumber() const -> bool; void SetShowTileNumber(bool newTileNumbers); + void SetBoundaryTogetherWithNotches(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + private: Unit m_unit{Unit::Cm}; @@ -376,6 +380,8 @@ private: bool m_printTilesScheme{false}; bool m_showTileNumbers{false}; + + bool m_togetherWithNotches{false}; }; #endif // VPLAYOUTSETTINGS_H diff --git a/src/app/puzzle/layout/vpsheet.cpp b/src/app/puzzle/layout/vpsheet.cpp index 822661c0f..a6835764a 100644 --- a/src/app/puzzle/layout/vpsheet.cpp +++ b/src/app/puzzle/layout/vpsheet.cpp @@ -334,6 +334,8 @@ void VPSheetSceneData::ConnectPiece(VPGraphicsPiece *piece) &VPGraphicsPieceControls::on_HideHandles); QObject::connect(piece, &VPGraphicsPiece::HideTransformationHandles, m_rotationOrigin, &VPGraphicsTransformationOrigin::on_HideHandles); + QObject::connect(layout.data(), &VPLayout::BoundaryTogetherWithNotchesChanged, piece, + &VPGraphicsPiece::on_RefreshPiece); } // VPSheet diff --git a/src/app/puzzle/scene/vpgraphicspiece.cpp b/src/app/puzzle/scene/vpgraphicspiece.cpp index b7e0b9b4d..079a98c50 100644 --- a/src/app/puzzle/scene/vpgraphicspiece.cpp +++ b/src/app/puzzle/scene/vpgraphicspiece.cpp @@ -44,6 +44,7 @@ #include "../layout/vpsheet.h" #include "../vformat/vsinglelineoutlinechar.h" #include "../vgeometry/vlayoutplacelabel.h" +#include "../vlayout/vboundary.h" #include "../vlayout/vgraphicsfillitem.h" #include "../vlayout/vlayoutpiecepath.h" #include "../vlayout/vtextmanager.h" @@ -650,24 +651,59 @@ void VPGraphicsPiece::PaintPiece(QPainter *painter) //--------------------------------------------------------------------------------------------------------------------- void VPGraphicsPiece::PaintSeamLine(QPainter *painter, const VPPiecePtr &piece) { - if (not piece->IsHideMainPath() || not piece->IsSeamAllowance()) + if (piece->IsSeamAllowance() && not piece->IsHideMainPath() && not piece->IsSeamAllowanceBuiltIn()) { QVector seamLinePoints = piece->GetMappedContourPoints(); - if (!seamLinePoints.isEmpty()) + + if (seamLinePoints.isEmpty()) { - m_seamLine.moveTo(seamLinePoints.constFirst()); - for (int i = 1; i < seamLinePoints.size(); i++) + return; + } + + VPLayoutPtr layout = piece->Layout(); + if (layout.isNull()) + { + return; + } + + if (layout->LayoutSettings().IsBoundaryTogetherWithNotches()) + { + QVector passmarks = piece->GetMappedPassmarks(); + + bool seamAllowance = piece->IsSeamAllowance() && piece->IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = piece->IsSeamAllowance() && piece->IsSeamAllowanceBuiltIn(); + + VBoundary boundary(seamLinePoints, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(piece->GetName()); + const QList sequence = boundary.Combine(passmarks, false, false); + + QVector combinedBoundary; + for (const auto &item : sequence) { - m_seamLine.lineTo(seamLinePoints.at(i)); + const auto path = item.item.value().Points(); + QVector convertedPoints; + CastTo(path, convertedPoints); + combinedBoundary += convertedPoints; } - if (painter != nullptr) - { - painter->save(); - painter->setBrush(piece->IsSelected() ? SelectionBrush() : NoBrush()); - painter->drawPath(m_seamLine); - painter->restore(); - } + m_seamLine.addPolygon(QPolygonF(combinedBoundary)); + m_seamLine.closeSubpath(); + } + else + { + QVector convertedPoints; + CastTo(seamLinePoints, convertedPoints); + + m_seamLine.addPolygon(QPolygonF(convertedPoints)); + m_seamLine.closeSubpath(); + } + + if (painter != nullptr) + { + painter->save(); + painter->setBrush(piece->IsSelected() ? SelectionBrush() : NoBrush()); + painter->drawPath(m_seamLine); + painter->restore(); } } } @@ -678,21 +714,55 @@ void VPGraphicsPiece::PaintCuttingLine(QPainter *painter, const VPPiecePtr &piec if (piece->IsSeamAllowance() && not piece->IsSeamAllowanceBuiltIn()) { QVector cuttingLinepoints = piece->GetMappedSeamAllowancePoints(); - if (!cuttingLinepoints.isEmpty()) + if (cuttingLinepoints.isEmpty()) { - m_cuttingLine.moveTo(cuttingLinepoints.constFirst()); - for (int i = 1; i < cuttingLinepoints.size(); i++) + return; + } + + VPLayoutPtr layout = piece->Layout(); + if (layout.isNull()) + { + return; + } + + if (layout->LayoutSettings().IsBoundaryTogetherWithNotches()) + { + const QVector passmarks = piece->GetMappedPassmarks(); + + bool seamAllowance = piece->IsSeamAllowance() && !piece->IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = piece->IsSeamAllowance() && piece->IsSeamAllowanceBuiltIn(); + + VBoundary boundary(cuttingLinepoints, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(piece->GetName()); + const QList sequence = boundary.Combine(passmarks, false, false); + + QVector combinedBoundary; + for (const auto &item : sequence) { - m_cuttingLine.lineTo(cuttingLinepoints.at(i)); + const auto path = item.item.value().Points(); + QVector convertedPoints; + CastTo(path, convertedPoints); + combinedBoundary += convertedPoints; } - if (painter != nullptr) - { - painter->save(); - painter->setBrush(piece->IsSelected() ? SelectionBrush() : NoBrush()); - painter->drawPath(m_cuttingLine); - painter->restore(); - } + m_cuttingLine.addPolygon(QPolygonF(combinedBoundary)); + m_cuttingLine.closeSubpath(); + } + else + { + QVector convertedPoints; + CastTo(cuttingLinepoints, convertedPoints); + + m_cuttingLine.addPolygon(QPolygonF(convertedPoints)); + m_cuttingLine.closeSubpath(); + } + + if (painter != nullptr) + { + painter->save(); + painter->setBrush(piece->IsSelected() ? SelectionBrush() : NoBrush()); + painter->drawPath(m_cuttingLine); + painter->restore(); } } } @@ -721,6 +791,17 @@ void VPGraphicsPiece::PaintInternalPaths(QPainter *painter, const VPPiecePtr &pi //--------------------------------------------------------------------------------------------------------------------- void VPGraphicsPiece::PaintPassmarks(QPainter *painter, const VPPiecePtr &piece) { + VPLayoutPtr layout = piece->Layout(); + if (layout.isNull()) + { + return; + } + + if (layout->LayoutSettings().IsBoundaryTogetherWithNotches()) + { + return; + } + QVector passmarks = piece->GetMappedPassmarks(); for (auto &passmark : passmarks) { diff --git a/src/app/puzzle/vpmainwindow.cpp b/src/app/puzzle/vpmainwindow.cpp index 47ddd46ee..cd4c582f8 100644 --- a/src/app/puzzle/vpmainwindow.cpp +++ b/src/app/puzzle/vpmainwindow.cpp @@ -1205,6 +1205,8 @@ void VPMainWindow::InitPropertyTabLayout() } }); + connect(ui->checkBoxTogetherWithNotches, &QCheckBox::toggled, this, &VPMainWindow::TogetherWithNotchesChanged); + VPSettings *settings = VPApplication::VApp()->PuzzleSettings(); ui->doubleSpinBoxSheetPiecesGap->setMaximum( UnitConvertor(VPSettings::GetMaxLayoutPieceGap(), Unit::Px, settings->LayoutUnit())); @@ -1523,6 +1525,7 @@ void VPMainWindow::SetPropertyTabLayoutData() m_layout->LayoutSettings().GetWarningSuperpositionOfPieces()); SetCheckBoxValue(ui->checkBoxSheetStickyEdges, m_layout->LayoutSettings().GetStickyEdges()); SetCheckBoxValue(ui->checkBoxFollowGainline, m_layout->LayoutSettings().GetFollowGrainline()); + SetCheckBoxValue(ui->checkBoxTogetherWithNotches, m_layout->LayoutSettings().IsBoundaryTogetherWithNotches()); // set pieces gap SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPiecesGap, m_layout->LayoutSettings().GetPiecesGapConverted()); @@ -1559,6 +1562,7 @@ void VPMainWindow::SetPropertyTabLayoutData() SetCheckBoxValue(ui->checkBoxLayoutWarningPiecesSuperposition, false); SetCheckBoxValue(ui->checkBoxSheetStickyEdges, false); SetCheckBoxValue(ui->checkBoxFollowGainline, false); + SetCheckBoxValue(ui->checkBoxTogetherWithNotches, false); SetDoubleSpinBoxValue(ui->doubleSpinBoxSheetPiecesGap, 0); @@ -4743,6 +4747,38 @@ void VPMainWindow::UpdateShortcuts() } } +//--------------------------------------------------------------------------------------------------------------------- +void VPMainWindow::TogetherWithNotchesChanged(bool checked) +{ + if (m_layout.isNull()) + { + return; + } + + m_layout->LayoutSettings().SetBoundaryTogetherWithNotches(checked); + m_carrousel->RefreshPieceMiniature(); + + QList sheets = m_layout->GetAllSheets(); + for (const auto &sheet : sheets) + { + if (sheet.isNull()) + { + continue; + } + + QList pieces = sheet->GetPieces(); + for (const auto &piece : pieces) + { + if (not piece.isNull()) + { + emit m_layout->BoundaryTogetherWithNotchesChanged(piece); + } + } + } + + LayoutWasSaved(false); +} + //--------------------------------------------------------------------------------------------------------------------- #if defined(Q_OS_MAC) void VPMainWindow::AboutToShowDockMenu() diff --git a/src/app/puzzle/vpmainwindow.h b/src/app/puzzle/vpmainwindow.h index eb97c418d..247dca470 100644 --- a/src/app/puzzle/vpmainwindow.h +++ b/src/app/puzzle/vpmainwindow.h @@ -297,6 +297,8 @@ private slots: void UpdateShortcuts(); + void TogetherWithNotchesChanged(bool checked); + private: Q_DISABLE_COPY_MOVE(VPMainWindow) // NOLINT Ui::VPMainWindow *ui; diff --git a/src/app/puzzle/vpmainwindow.ui b/src/app/puzzle/vpmainwindow.ui index f54e7f8ee..b6cf5c2c7 100644 --- a/src/app/puzzle/vpmainwindow.ui +++ b/src/app/puzzle/vpmainwindow.ui @@ -1715,6 +1715,13 @@ + + + + Boundary together with notches + + + @@ -2427,8 +2434,8 @@ - - + + diff --git a/src/app/puzzle/xml/vplayoutfilereader.cpp b/src/app/puzzle/xml/vplayoutfilereader.cpp index c39e4c19c..719e8170f 100644 --- a/src/app/puzzle/xml/vplayoutfilereader.cpp +++ b/src/app/puzzle/xml/vplayoutfilereader.cpp @@ -341,6 +341,8 @@ void VPLayoutFileReader::ReadControl(const VPLayoutPtr &layout) layout->LayoutSettings().SetStickyEdges(ReadAttributeBool(attribs, ML::AttrStickyEdges, trueStr)); layout->LayoutSettings().SetPiecesGap(qMax(ReadAttributeDouble(attribs, ML::AttrPiecesGap, QChar('0')), 0.0)); layout->LayoutSettings().SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainline, falseStr)); + layout->LayoutSettings().SetBoundaryTogetherWithNotches( + ReadAttributeBool(attribs, ML::AttrBoundaryTogetherWithNotches, falseStr)); readElementText(); } diff --git a/src/app/puzzle/xml/vplayoutfilewriter.cpp b/src/app/puzzle/xml/vplayoutfilewriter.cpp index 4a25aad57..7feb206ee 100644 --- a/src/app/puzzle/xml/vplayoutfilewriter.cpp +++ b/src/app/puzzle/xml/vplayoutfilewriter.cpp @@ -173,6 +173,7 @@ void VPLayoutFileWriter::WriteLayoutProperties(const VPLayoutPtr &layout) SetAttribute(ML::AttrStickyEdges, layout->LayoutSettings().GetStickyEdges()); SetAttribute(ML::AttrPiecesGap, layout->LayoutSettings().GetPiecesGap()); SetAttribute(ML::AttrFollowGrainline, layout->LayoutSettings().GetFollowGrainline()); + SetAttribute(ML::AttrBoundaryTogetherWithNotches, layout->LayoutSettings().IsBoundaryTogetherWithNotches()); writeEndElement(); // control WriteTiles(layout); diff --git a/src/app/puzzle/xml/vplayoutliterals.cpp b/src/app/puzzle/xml/vplayoutliterals.cpp index 097f2d4c8..e72a34917 100644 --- a/src/app/puzzle/xml/vplayoutliterals.cpp +++ b/src/app/puzzle/xml/vplayoutliterals.cpp @@ -68,59 +68,60 @@ const QString TagScale = QStringLiteral("scale"); // NOLINT(ce const QString TagWatermark = QStringLiteral("watermark"); // NOLINT(cert-err58-cpp) const QString TagPoint = QStringLiteral("point"); // NOLINT(cert-err58-cpp) -const QString AttrWarningSuperposition = QStringLiteral("warningSuperposition"); // NOLINT(cert-err58-cpp) -const QString AttrWarningOutOfBound = QStringLiteral("warningOutOfBound"); // NOLINT(cert-err58-cpp) -const QString AttrStickyEdges = QStringLiteral("stickyEdges"); // NOLINT(cert-err58-cpp) -const QString AttrPiecesGap = QStringLiteral("piecesGap"); // NOLINT(cert-err58-cpp) -const QString AttrVisible = QStringLiteral("visible"); // NOLINT(cert-err58-cpp) -const QString AttrMatchingMarks = QStringLiteral("matchingMarks"); // NOLINT(cert-err58-cpp) -const QString AttrName = QStringLiteral("name"); // NOLINT(cert-err58-cpp) -const QString AttrLeft = QStringLiteral("left"); // NOLINT(cert-err58-cpp) -const QString AttrTop = QStringLiteral("top"); // NOLINT(cert-err58-cpp) -const QString AttrRight = QStringLiteral("right"); // NOLINT(cert-err58-cpp) -const QString AttrBottom = QStringLiteral("bottom"); // NOLINT(cert-err58-cpp) -const QString AttrWidth = QStringLiteral("width"); // NOLINT(cert-err58-cpp) -const QString AttrLength = QStringLiteral("length"); // NOLINT(cert-err58-cpp) -const QString AttrFollowGrainline = QStringLiteral("followGrainline"); // NOLINT(cert-err58-cpp) -const QString AttrUID = QStringLiteral("uid"); // NOLINT(cert-err58-cpp) -const QString AttrMirrored = QStringLiteral("mirrored"); // NOLINT(cert-err58-cpp) -const QString AttrForbidFlipping = QStringLiteral("forbidFlipping"); // NOLINT(cert-err58-cpp) -const QString AttrForceFlipping = QStringLiteral("forceFlipping"); // NOLINT(cert-err58-cpp) -const QString AttrSewLineOnDrawing = QStringLiteral("sewLineOnDrawing"); // NOLINT(cert-err58-cpp) -const QString AttrTransform = QStringLiteral("transform"); // NOLINT(cert-err58-cpp) -const QString AttrShowSeamline = QStringLiteral("showSeamline"); // NOLINT(cert-err58-cpp) -const QString AttrEnabled = QStringLiteral("enabled"); // NOLINT(cert-err58-cpp) -const QString AttrBuiltIn = QStringLiteral("builtIn"); // NOLINT(cert-err58-cpp) -const QString AttrArrowDirection = QStringLiteral("arrowDirection"); // NOLINT(cert-err58-cpp) -const QString AttrType = QStringLiteral("type"); // NOLINT(cert-err58-cpp) -const QString AttrBaseLine = QStringLiteral("baseLine"); // NOLINT(cert-err58-cpp) -const QString AttrPath = QStringLiteral("path"); // NOLINT(cert-err58-cpp) -const QString AttrCut = QStringLiteral("cut"); // NOLINT(cert-err58-cpp) -const QString AttrPenStyle = QStringLiteral("penStyle"); // NOLINT(cert-err58-cpp) -const QString AttrCenter = QStringLiteral("center"); // NOLINT(cert-err58-cpp) -const QString AttrBox = QStringLiteral("box"); // NOLINT(cert-err58-cpp) -const QString AttrShape = QStringLiteral("shape"); // NOLINT(cert-err58-cpp) -const QString AttrFont = QStringLiteral("font"); // NOLINT(cert-err58-cpp) -const QString AttrSVGFont = QStringLiteral("svgFont"); // NOLINT(cert-err58-cpp) -const QString AttrFontSize = QStringLiteral("fontSize"); // NOLINT(cert-err58-cpp) -const QString AttrBold = QStringLiteral("bold"); // NOLINT(cert-err58-cpp) -const QString AttrItalic = QStringLiteral("italic"); // NOLINT(cert-err58-cpp) -const QString AttrAlignment = QStringLiteral("alignment"); // NOLINT(cert-err58-cpp) -const QString AttrGradationLabel = QStringLiteral("gradationLabel"); // NOLINT(cert-err58-cpp) -const QString AttrCopyNumber = QStringLiteral("copyNumber"); // NOLINT(cert-err58-cpp) -const QString AttrGrainlineType = QStringLiteral("grainlineType"); // NOLINT(cert-err58-cpp) -const QString AttrXScale = QStringLiteral("xScale"); // NOLINT(cert-err58-cpp) -const QString AttrYScale = QStringLiteral("yScale"); // NOLINT(cert-err58-cpp) -const QString AttrIgnoreMargins = QStringLiteral("ignoreMargins"); // NOLINT(cert-err58-cpp) -const QString AttrShowPreview = QStringLiteral("showPreview"); // NOLINT(cert-err58-cpp) -const QString AttrPrintScheme = QStringLiteral("printScheme"); // NOLINT(cert-err58-cpp) -const QString AttrTileNumber = QStringLiteral("tileNumber"); // NOLINT(cert-err58-cpp) -const QString AttrZValue = QStringLiteral("zValue"); // NOLINT(cert-err58-cpp) -const QString AttrX = QStringLiteral("x"); // NOLINT(cert-err58-cpp) -const QString AttrY = QStringLiteral("y"); // NOLINT(cert-err58-cpp) -const QString AttrTurnPoint = QStringLiteral("turnPoint"); // NOLINT(cert-err58-cpp) -const QString AttrCurvePoint = QStringLiteral("curvePoint"); // NOLINT(cert-err58-cpp) -const QString AttrClockwiseOpening = QStringLiteral("clockwiseOpening"); // NOLINT(cert-err58-cpp) +const QString AttrWarningSuperposition = QStringLiteral("warningSuperposition"); // NOLINT(cert-err58-cpp) +const QString AttrWarningOutOfBound = QStringLiteral("warningOutOfBound"); // NOLINT(cert-err58-cpp) +const QString AttrStickyEdges = QStringLiteral("stickyEdges"); // NOLINT(cert-err58-cpp) +const QString AttrPiecesGap = QStringLiteral("piecesGap"); // NOLINT(cert-err58-cpp) +const QString AttrVisible = QStringLiteral("visible"); // NOLINT(cert-err58-cpp) +const QString AttrMatchingMarks = QStringLiteral("matchingMarks"); // NOLINT(cert-err58-cpp) +const QString AttrName = QStringLiteral("name"); // NOLINT(cert-err58-cpp) +const QString AttrLeft = QStringLiteral("left"); // NOLINT(cert-err58-cpp) +const QString AttrTop = QStringLiteral("top"); // NOLINT(cert-err58-cpp) +const QString AttrRight = QStringLiteral("right"); // NOLINT(cert-err58-cpp) +const QString AttrBottom = QStringLiteral("bottom"); // NOLINT(cert-err58-cpp) +const QString AttrWidth = QStringLiteral("width"); // NOLINT(cert-err58-cpp) +const QString AttrLength = QStringLiteral("length"); // NOLINT(cert-err58-cpp) +const QString AttrFollowGrainline = QStringLiteral("followGrainline"); // NOLINT(cert-err58-cpp) +const QString AttrBoundaryTogetherWithNotches = QStringLiteral("boundaryTogetherWithNotches"); // NOLINT(cert-err58-cpp) +const QString AttrUID = QStringLiteral("uid"); // NOLINT(cert-err58-cpp) +const QString AttrMirrored = QStringLiteral("mirrored"); // NOLINT(cert-err58-cpp) +const QString AttrForbidFlipping = QStringLiteral("forbidFlipping"); // NOLINT(cert-err58-cpp) +const QString AttrForceFlipping = QStringLiteral("forceFlipping"); // NOLINT(cert-err58-cpp) +const QString AttrSewLineOnDrawing = QStringLiteral("sewLineOnDrawing"); // NOLINT(cert-err58-cpp) +const QString AttrTransform = QStringLiteral("transform"); // NOLINT(cert-err58-cpp) +const QString AttrShowSeamline = QStringLiteral("showSeamline"); // NOLINT(cert-err58-cpp) +const QString AttrEnabled = QStringLiteral("enabled"); // NOLINT(cert-err58-cpp) +const QString AttrBuiltIn = QStringLiteral("builtIn"); // NOLINT(cert-err58-cpp) +const QString AttrArrowDirection = QStringLiteral("arrowDirection"); // NOLINT(cert-err58-cpp) +const QString AttrType = QStringLiteral("type"); // NOLINT(cert-err58-cpp) +const QString AttrBaseLine = QStringLiteral("baseLine"); // NOLINT(cert-err58-cpp) +const QString AttrPath = QStringLiteral("path"); // NOLINT(cert-err58-cpp) +const QString AttrCut = QStringLiteral("cut"); // NOLINT(cert-err58-cpp) +const QString AttrPenStyle = QStringLiteral("penStyle"); // NOLINT(cert-err58-cpp) +const QString AttrCenter = QStringLiteral("center"); // NOLINT(cert-err58-cpp) +const QString AttrBox = QStringLiteral("box"); // NOLINT(cert-err58-cpp) +const QString AttrShape = QStringLiteral("shape"); // NOLINT(cert-err58-cpp) +const QString AttrFont = QStringLiteral("font"); // NOLINT(cert-err58-cpp) +const QString AttrSVGFont = QStringLiteral("svgFont"); // NOLINT(cert-err58-cpp) +const QString AttrFontSize = QStringLiteral("fontSize"); // NOLINT(cert-err58-cpp) +const QString AttrBold = QStringLiteral("bold"); // NOLINT(cert-err58-cpp) +const QString AttrItalic = QStringLiteral("italic"); // NOLINT(cert-err58-cpp) +const QString AttrAlignment = QStringLiteral("alignment"); // NOLINT(cert-err58-cpp) +const QString AttrGradationLabel = QStringLiteral("gradationLabel"); // NOLINT(cert-err58-cpp) +const QString AttrCopyNumber = QStringLiteral("copyNumber"); // NOLINT(cert-err58-cpp) +const QString AttrGrainlineType = QStringLiteral("grainlineType"); // NOLINT(cert-err58-cpp) +const QString AttrXScale = QStringLiteral("xScale"); // NOLINT(cert-err58-cpp) +const QString AttrYScale = QStringLiteral("yScale"); // NOLINT(cert-err58-cpp) +const QString AttrIgnoreMargins = QStringLiteral("ignoreMargins"); // NOLINT(cert-err58-cpp) +const QString AttrShowPreview = QStringLiteral("showPreview"); // NOLINT(cert-err58-cpp) +const QString AttrPrintScheme = QStringLiteral("printScheme"); // NOLINT(cert-err58-cpp) +const QString AttrTileNumber = QStringLiteral("tileNumber"); // NOLINT(cert-err58-cpp) +const QString AttrZValue = QStringLiteral("zValue"); // NOLINT(cert-err58-cpp) +const QString AttrX = QStringLiteral("x"); // NOLINT(cert-err58-cpp) +const QString AttrY = QStringLiteral("y"); // NOLINT(cert-err58-cpp) +const QString AttrTurnPoint = QStringLiteral("turnPoint"); // NOLINT(cert-err58-cpp) +const QString AttrCurvePoint = QStringLiteral("curvePoint"); // NOLINT(cert-err58-cpp) +const QString AttrClockwiseOpening = QStringLiteral("clockwiseOpening"); // NOLINT(cert-err58-cpp) const QString oneWayUpStr = QStringLiteral("oneWayUp"); // NOLINT(cert-err58-cpp) const QString oneWayDownStr = QStringLiteral("oneWayDown"); // NOLINT(cert-err58-cpp) diff --git a/src/app/puzzle/xml/vplayoutliterals.h b/src/app/puzzle/xml/vplayoutliterals.h index 14b92e0dd..6b0691a0d 100644 --- a/src/app/puzzle/xml/vplayoutliterals.h +++ b/src/app/puzzle/xml/vplayoutliterals.h @@ -81,6 +81,7 @@ extern const QString AttrBottom; extern const QString AttrWidth; extern const QString AttrLength; extern const QString AttrFollowGrainline; +extern const QString AttrBoundaryTogetherWithNotches; extern const QString AttrUID; extern const QString AttrMirrored; extern const QString AttrForbidFlipping; diff --git a/src/app/valentina/core/vcmdexport.cpp b/src/app/valentina/core/vcmdexport.cpp index ded397260..1c2394ead 100644 --- a/src/app/valentina/core/vcmdexport.cpp +++ b/src/app/valentina/core/vcmdexport.cpp @@ -165,6 +165,7 @@ auto VCommandLine::DefaultGenerator() const -> VLayoutGeneratorPtr diag.SetUnitePages(IsOptionSet(LONG_OPTION_UNITE)); diag.SetSaveLength(IsOptionSet(LONG_OPTION_SAVELENGTH)); diag.SetPreferOneSheetSolution(IsOptionSet(LONG_OPTION_PREFER_ONE_SHEET_SOLUTION)); + diag.SetBoundaryTogetherWithNotches(IsOptionSet(LONG_OPTION_BOUNDARY_TOGETHER_WITH_NOTCHES)); diag.SetGroup(OptGroup()); if (IsOptionSet(LONG_OPTION_IGNORE_MARGINS)) @@ -718,6 +719,8 @@ void VCommandLine::InitCommandLineOptions() "supports only a maximum of 32768x32768 px images.")}, {LONG_OPTION_PREFER_ONE_SHEET_SOLUTION, translate("VCommandLine", "Prefer one sheet layout solution (export mode).")}, + {LONG_OPTION_BOUNDARY_TOGETHER_WITH_NOTCHES, + translate("VCommandLine", "Export boundary together with notches (export mode).")}, //============================================================================================================== {{SINGLE_OPTION_SAVELENGTH, LONG_OPTION_SAVELENGTH}, translate("VCommandLine", "Save length of the sheet if set (export mode). The option tells the program to use " diff --git a/src/app/valentina/dialogs/dialoglayoutsettings.cpp b/src/app/valentina/dialogs/dialoglayoutsettings.cpp index 770f12dea..6612af7fc 100644 --- a/src/app/valentina/dialogs/dialoglayoutsettings.cpp +++ b/src/app/valentina/dialogs/dialoglayoutsettings.cpp @@ -383,6 +383,30 @@ void DialogLayoutSettings::SetNestQuantity(bool state) ui->checkBoxNestQuantity->setChecked(state); } +//--------------------------------------------------------------------------------------------------------------------- +void DialogLayoutSettings::SetBoundaryTogetherWithNotches(bool value) +{ + ui->checkBoxTogetherWithNotches->setChecked(value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto DialogLayoutSettings::IsBoundaryTogetherWithNotches() const -> bool +{ + return ui->checkBoxTogetherWithNotches->isChecked(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void DialogLayoutSettings::SetShowLayoutAllowance(bool value) +{ + ui->checkBoxShowLayoutAllowance->setChecked(value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto DialogLayoutSettings::IsShowLayoutAllowance() const -> bool +{ + return ui->checkBoxShowLayoutAllowance->isChecked(); +} + //--------------------------------------------------------------------------------------------------------------------- auto DialogLayoutSettings::SelectedPrinter() const -> QString { @@ -641,6 +665,8 @@ void DialogLayoutSettings::DialogAccepted() m_generator->SetMultiplier(GetMultiplier()); m_generator->SetTextAsPaths(IsTextAsPaths()); m_generator->SetNestQuantity(IsNestQuantity()); + m_generator->SetBoundaryTogetherWithNotches(IsBoundaryTogetherWithNotches()); + m_generator->SetShowLayoutAllowance(IsShowLayoutAllowance()); if (IsIgnoreAllFields()) { @@ -712,6 +738,7 @@ void DialogLayoutSettings::RestoreDefaults() SetEfficiencyCoefficient(VValentinaSettings::GetDefEfficiencyCoefficient()); SetNestQuantity(VValentinaSettings::GetDefLayoutNestQuantity()); SetPreferOneSheetSolution(VValentinaSettings::GetDefLayoutPreferOneSheetSolution()); + SetBoundaryTogetherWithNotches(VValentinaSettings::GetDefLayoutBoundaryTogetherWithNotches()); CorrectMaxFileds(); IgnoreAllFields(ui->checkBoxIgnoreFileds->isChecked()); @@ -1037,6 +1064,7 @@ void DialogLayoutSettings::ReadSettings() SetMultiplier(settings->GetMultiplier()); SetTextAsPaths(settings->GetTextAsPaths()); SetNestQuantity(settings->GetLayoutNestQuantity()); + SetBoundaryTogetherWithNotches(settings->GetLayoutBoundaryTogetherWithNotches()); FindTemplate(); @@ -1067,6 +1095,7 @@ void DialogLayoutSettings::WriteSettings() const settings->SetNestingTime(GetNestingTime()); settings->SetEfficiencyCoefficient(GetEfficiencyCoefficient()); settings->SetLayoutNestQuantity(IsNestQuantity()); + settings->SetLayoutBoundaryTogetherWithNotches(IsBoundaryTogetherWithNotches()); } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/app/valentina/dialogs/dialoglayoutsettings.h b/src/app/valentina/dialogs/dialoglayoutsettings.h index 7bdd6f243..79d49b165 100644 --- a/src/app/valentina/dialogs/dialoglayoutsettings.h +++ b/src/app/valentina/dialogs/dialoglayoutsettings.h @@ -37,7 +37,7 @@ namespace Ui { - class DialogLayoutSettings; +class DialogLayoutSettings; } class VLayoutGenerator; @@ -45,6 +45,7 @@ class VLayoutGenerator; class DialogLayoutSettings : public VAbstractLayoutDialog { Q_OBJECT // NOLINT + public: explicit DialogLayoutSettings(VLayoutGenerator *generator, QWidget *parent = nullptr, bool disableSettings = false); ~DialogLayoutSettings() override; @@ -106,19 +107,26 @@ public: auto IsNestQuantity() const -> bool; void SetNestQuantity(bool state); + void SetBoundaryTogetherWithNotches(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + + void SetShowLayoutAllowance(bool value); + auto IsShowLayoutAllowance() const -> bool; + auto SelectedPrinter() const -> QString; void EnableLandscapeOrientation(); - //support functions for the command line parser which uses invisible dialog to properly build layout generator - auto SelectTemplate(const PaperSizeTemplate& id) -> bool; + // support functions for the command line parser which uses invisible dialog to properly build layout generator + auto SelectTemplate(const PaperSizeTemplate &id) -> bool; static auto MakeHelpTemplateList() -> QString; static auto MakeHelpTiledPdfTemplateList() -> QString; - auto SelectPaperUnit(const QString& units) -> bool; - auto SelectLayoutUnit(const QString& units) -> bool; + auto SelectPaperUnit(const QString &units) -> bool; + auto SelectLayoutUnit(const QString &units) -> bool; auto LayoutToPixels(qreal value) const -> qreal; auto PageToPixels(qreal value) const -> qreal; static auto MakeGroupsHelp() -> QString; + protected: void showEvent(QShowEvent *event) override; void resizeEvent(QResizeEvent *event) override; @@ -138,6 +146,7 @@ private slots: void CorrectMaxFileds(); void IgnoreAllFields(int state); + private: // cppcheck-suppress unknownMacro Q_DISABLE_COPY_MOVE(DialogLayoutSettings) // NOLINT diff --git a/src/app/valentina/dialogs/dialoglayoutsettings.ui b/src/app/valentina/dialogs/dialoglayoutsettings.ui index 4d0b050f2..97493cc15 100644 --- a/src/app/valentina/dialogs/dialoglayoutsettings.ui +++ b/src/app/valentina/dialogs/dialoglayoutsettings.ui @@ -340,6 +340,29 @@ + + + + Boundary together with notches + + + + + + + Debug + + + + + + Show layout allowance + + + + + + diff --git a/src/app/valentina/dialogs/dialogsavelayout.cpp b/src/app/valentina/dialogs/dialogsavelayout.cpp index 5a9d5f955..9f51f0f40 100644 --- a/src/app/valentina/dialogs/dialogsavelayout.cpp +++ b/src/app/valentina/dialogs/dialogsavelayout.cpp @@ -440,22 +440,26 @@ void DialogSaveLayout::ShowExample() ui->checkBoxBinaryDXF->setVisible(false); ui->checkBoxTextAsPaths->setVisible(false); ui->checkBoxShowGrainline->setVisible(false); + ui->checkBoxTogetherWithNotches->setVisible(false); switch (currentFormat) { case LayoutExportFormats::DXF_AAMA: case LayoutExportFormats::DXF_ASTM: ui->checkBoxBinaryDXF->setVisible(true); + ui->checkBoxTogetherWithNotches->setVisible(m_mode != Draw::Layout); break; case LayoutExportFormats::PDFTiled: ui->groupBoxPaperFormat->setEnabled(true); ui->groupBoxMargins->setEnabled(true); ui->checkBoxTextAsPaths->setVisible(m_mode != Draw::Layout); ui->checkBoxShowGrainline->setVisible(true); + ui->checkBoxTogetherWithNotches->setVisible(m_mode != Draw::Layout); break; case LayoutExportFormats::HPGL: case LayoutExportFormats::HPGL2: ui->checkBoxShowGrainline->setVisible(true); + ui->checkBoxTogetherWithNotches->setVisible(true); break; case LayoutExportFormats::SVG: case LayoutExportFormats::PDF: @@ -465,6 +469,7 @@ void DialogSaveLayout::ShowExample() case LayoutExportFormats::TIF: ui->checkBoxTextAsPaths->setVisible(m_mode != Draw::Layout); ui->checkBoxShowGrainline->setVisible(true); + ui->checkBoxTogetherWithNotches->setVisible(m_mode != Draw::Layout); break; case LayoutExportFormats::DXF_AC1006_Flat: case LayoutExportFormats::DXF_AC1009_Flat: @@ -478,6 +483,7 @@ void DialogSaveLayout::ShowExample() ui->checkBoxBinaryDXF->setVisible(true); ui->checkBoxTextAsPaths->setVisible(m_mode != Draw::Layout); ui->checkBoxShowGrainline->setVisible(true); + ui->checkBoxTogetherWithNotches->setVisible(m_mode != Draw::Layout); break; default: ui->labelOptionsNotAvailable->setVisible(true); @@ -632,6 +638,18 @@ auto DialogSaveLayout::GetYScale() const -> qreal return ui->doubleSpinBoxVerticalScale->value() / 100.; } +//--------------------------------------------------------------------------------------------------------------------- +void DialogSaveLayout::SetBoundaryTogetherWithNotches(bool value) +{ + ui->checkBoxTogetherWithNotches->setChecked(value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto DialogSaveLayout::IsBoundaryTogetherWithNotches() const -> bool +{ + return ui->checkBoxTogetherWithNotches->isChecked(); +} + //--------------------------------------------------------------------------------------------------------------------- void DialogSaveLayout::showEvent(QShowEvent *event) { diff --git a/src/app/valentina/dialogs/dialogsavelayout.h b/src/app/valentina/dialogs/dialogsavelayout.h index 21b5e1d4d..c02a1d3e4 100644 --- a/src/app/valentina/dialogs/dialogsavelayout.h +++ b/src/app/valentina/dialogs/dialogsavelayout.h @@ -35,10 +35,10 @@ namespace Ui { - class DialogSaveLAyout; +class DialogSaveLAyout; } -class DialogSaveLayout : public VAbstractLayoutDialog +class DialogSaveLayout : public VAbstractLayoutDialog { Q_OBJECT // NOLINT @@ -60,7 +60,7 @@ public: auto IsShowGrainline() const -> bool; static auto MakeHelpFormatList() -> QString; - void SetDestinationPath(const QString& cmdDestinationPath); + void SetDestinationPath(const QString &cmdDestinationPath); auto Mode() const -> Draw; @@ -84,6 +84,9 @@ public: void SetYScale(qreal scale); auto GetYScale() const -> qreal; + void SetBoundaryTogetherWithNotches(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + protected: void showEvent(QShowEvent *event) override; @@ -94,6 +97,7 @@ private slots: void ToggleScaleConnection(); void HorizontalScaleChanged(double d); void VerticalScaleChanged(double d); + private: // cppcheck-suppress unknownMacro Q_DISABLE_COPY_MOVE(DialogSaveLayout) // NOLINT @@ -105,9 +109,9 @@ private: bool m_scaleConnected{true}; static bool havePdf; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) - static bool tested; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) + static bool tested; // NOLINT(cppcoreguidelines-avoid-non-const-global-variables) static auto SupportPSTest() -> bool; - static auto InitFormats() -> QVector >; + static auto InitFormats() -> QVector>; void RemoveFormatFromList(LayoutExportFormats format); diff --git a/src/app/valentina/dialogs/dialogsavelayout.ui b/src/app/valentina/dialogs/dialogsavelayout.ui index 0e5ee90fe..dd3a43a1c 100644 --- a/src/app/valentina/dialogs/dialogsavelayout.ui +++ b/src/app/valentina/dialogs/dialogsavelayout.ui @@ -7,7 +7,7 @@ 0 0 544 - 401 + 439 @@ -138,7 +138,14 @@ Show grainline - true + false + + + + + + + Boundary together with notches @@ -275,7 +282,7 @@ - + @@ -482,7 +489,7 @@ - + @@ -502,7 +509,7 @@ - + diff --git a/src/app/valentina/mainwindow.cpp b/src/app/valentina/mainwindow.cpp index a82142d05..7655b8428 100644 --- a/src/app/valentina/mainwindow.cpp +++ b/src/app/valentina/mainwindow.cpp @@ -4470,6 +4470,7 @@ void MainWindow::Clear() ui->actionShowCurveDetails->setEnabled(false); ui->actionShowAccuracyRadius->setEnabled(false); ui->actionShowMainPath->setEnabled(false); + ui->actionBoundaryTogetherWithNotches->setEnabled(false); ui->actionLoadIndividual->setEnabled(false); ui->actionLoadMultisize->setEnabled(false); ui->actionUnloadMeasurements->setEnabled(false); @@ -4722,6 +4723,7 @@ void MainWindow::SetEnableWidgets(bool enable) ui->actionShowCurveDetails->setEnabled(enableOnDrawStage); ui->actionShowAccuracyRadius->setEnabled(enableOnDesignStage); ui->actionShowMainPath->setEnabled(enableOnDetailsStage); + ui->actionBoundaryTogetherWithNotches->setEnabled(enableOnDetailsStage); ui->actionLoadIndividual->setEnabled(enableOnDesignStage); ui->actionLoadMultisize->setEnabled(enableOnDesignStage); ui->actionUnloadMeasurements->setEnabled(enableOnDesignStage); @@ -5218,6 +5220,29 @@ void MainWindow::ActionShowMainPath_triggered(bool checked) QGuiApplication::restoreOverrideCursor(); } +//--------------------------------------------------------------------------------------------------------------------- +void MainWindow::ActionBoundaryTogetherWithNotches_triggered(bool checked) +{ + VAbstractValApplication::VApp()->ValentinaSettings()->SetBoundaryTogetherWithNotches(checked); + const QList ids = pattern->DataPieces()->keys(); + const bool updateChildren = false; + QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + for (const auto &id : ids) + { + try + { + if (auto *tool = qobject_cast(VAbstractPattern::getTool(id))) + { + tool->RefreshGeometry(updateChildren); + } + } + catch (VExceptionBadId &) + { + } + } + QGuiApplication::restoreOverrideCursor(); +} + //--------------------------------------------------------------------------------------------------------------------- void MainWindow::ActionOpenTape_triggered() { @@ -6183,6 +6208,11 @@ void MainWindow::CreateActions() ui->actionShowMainPath->setChecked(VAbstractValApplication::VApp()->ValentinaSettings()->IsPieceShowMainPath()); connect(ui->actionShowMainPath, &QAction::triggered, this, &MainWindow::ActionShowMainPath_triggered); + ui->actionBoundaryTogetherWithNotches->setChecked( + VAbstractValApplication::VApp()->ValentinaSettings()->IsBoundaryTogetherWithNotches()); + connect(ui->actionBoundaryTogetherWithNotches, &QAction::triggered, this, + &MainWindow::ActionBoundaryTogetherWithNotches_triggered); + connect(ui->actionLoadIndividual, &QAction::triggered, this, &MainWindow::LoadIndividual); connect(ui->actionLoadMultisize, &QAction::triggered, this, &MainWindow::LoadMultisize); connect(ui->actionOpenTape, &QAction::triggered, this, &MainWindow::ActionOpenTape_triggered); @@ -6777,6 +6807,7 @@ void MainWindow::ExportLayoutAs(bool checked) { m_dialogSaveLayout = QSharedPointer(new DialogSaveLayout( static_cast(m_layoutSettings->LayoutScenes().size()), Draw::Layout, FileName(), this)); + m_dialogSaveLayout->SetBoundaryTogetherWithNotches(m_layoutSettings->IsBoundaryTogetherWithNotches()); if (m_dialogSaveLayout->exec() == QDialog::Rejected) { @@ -6821,9 +6852,8 @@ void MainWindow::ExportDetailsAs(bool checked) } catch (VException &e) { - QMessageBox::warning(this, tr("Export details"), - tr("Can't export details.") + QStringLiteral(" \n") + e.ErrorMessage(), QMessageBox::Ok, - QMessageBox::Ok); + QMessageBox::warning(this, tr("Export details"), tr("Can't export details.") + " \n"_L1 + e.ErrorMessage(), + QMessageBox::Ok, QMessageBox::Ok); return; } @@ -6832,6 +6862,9 @@ void MainWindow::ExportDetailsAs(bool checked) m_dialogSaveLayout = QSharedPointer(new DialogSaveLayout(1, Draw::Modeling, FileName(), this)); + VValentinaSettings *settings = VAbstractValApplication::VApp()->ValentinaSettings(); + m_dialogSaveLayout->SetBoundaryTogetherWithNotches(settings->IsBoundaryTogetherWithNotches()); + if (m_dialogSaveLayout->exec() == QDialog::Rejected) { m_dialogSaveLayout.clear(); diff --git a/src/app/valentina/mainwindow.h b/src/app/valentina/mainwindow.h index 10b0fe8cf..8fe614f9f 100644 --- a/src/app/valentina/mainwindow.h +++ b/src/app/valentina/mainwindow.h @@ -255,6 +255,7 @@ private slots: void ActionTable_triggered(); void ActionFinalMeasurements_triggered(); void ActionShowMainPath_triggered(bool checked); + void ActionBoundaryTogetherWithNotches_triggered(bool checked); void ActionOpenTape_triggered(); void UpdateShortcuts(); diff --git a/src/app/valentina/mainwindow.ui b/src/app/valentina/mainwindow.ui index 841b8acd8..c156c1b11 100644 --- a/src/app/valentina/mainwindow.ui +++ b/src/app/valentina/mainwindow.ui @@ -115,6 +115,7 @@ + @@ -2611,6 +2612,17 @@ QAction::NoRole + + + true + + + false + + + Boundary together with notches + + diff --git a/src/app/valentina/mainwindowsnogui.cpp b/src/app/valentina/mainwindowsnogui.cpp index 13107fa28..efcc65412 100644 --- a/src/app/valentina/mainwindowsnogui.cpp +++ b/src/app/valentina/mainwindowsnogui.cpp @@ -338,6 +338,7 @@ auto MainWindowsNoGUI::GenerateLayout(VLayoutGenerator &lGenerator) -> bool m_layoutSettings->SetAutoCropWidth(lGenerator.GetAutoCropWidth()); m_layoutSettings->SetUnitePages(lGenerator.IsUnitePages()); m_layoutSettings->SetLayoutStale(false); + m_layoutSettings->SetBoundaryTogetherWithNotches(lGenerator.IsBoundaryTogetherWithNotches()); papersCount = lGenerator.PapersCount(); hasResult = true; qDebug() << "Layout efficiency: " << efficiency; @@ -508,7 +509,7 @@ void MainWindowsNoGUI::ExportData(const QVector &listDetails) { for (int i = 0; i < detailsOnLayout.size(); ++i) { - const QString name = m_dialogSaveLayout->Path() + '/' + m_dialogSaveLayout->FileName() + + const QString name = m_dialogSaveLayout->Path() + '/'_L1 + m_dialogSaveLayout->FileName() + QString::number(i + 1) + VLayoutExporter::ExportFormatSuffix(m_dialogSaveLayout->Format()); @@ -582,13 +583,15 @@ void MainWindowsNoGUI::ExportDetailsAsFlatLayout(const QVector &li list.reserve(listDetails.count()); for (auto piece : listDetails) { - QGraphicsItem *item = piece.GetItem(m_dialogSaveLayout->IsTextAsPaths()); + QGraphicsItem *item = piece.GetItem(m_dialogSaveLayout->IsTextAsPaths(), + m_dialogSaveLayout->IsBoundaryTogetherWithNotches(), false); qreal diff = 0; if (piece.IsForceFlipping()) { const qreal x = item->boundingRect().x(); piece.Mirror(); - item = piece.GetItem(m_dialogSaveLayout->IsTextAsPaths()); + item = piece.GetItem(m_dialogSaveLayout->IsTextAsPaths(), + m_dialogSaveLayout->IsBoundaryTogetherWithNotches(), false); diff = item->boundingRect().x() - x; } @@ -624,7 +627,7 @@ void MainWindowsNoGUI::ExportDetailsAsFlatLayout(const QVector &li rect = scene->itemsBoundingRect().toRect(); - QGraphicsRectItem *paper = new QGraphicsRectItem(rect); + auto *paper = new QGraphicsRectItem(rect); paper->setPen(QPen(Qt::black, 1)); paper->setBrush(QBrush(Qt::white)); papers.append(paper); @@ -671,6 +674,7 @@ void MainWindowsNoGUI::ExportApparelLayout(const QVector &details, exporter.SetYScale(m_dialogSaveLayout->GetYScale()); exporter.SetBinaryDxfFormat(m_dialogSaveLayout->IsBinaryDXFFormat()); exporter.SetShowGrainline(m_dialogSaveLayout->IsShowGrainline()); + exporter.SetBoundaryTogetherWithNotches(m_dialogSaveLayout->IsBoundaryTogetherWithNotches()); switch (format) { @@ -720,14 +724,16 @@ void MainWindowsNoGUI::ExportDetailsAsApparelLayout(QVector listDe for (int i = 0; i < listDetails.count(); ++i) { VLayoutPiece piece = listDetails.at(i); - QGraphicsItem *item = piece.GetItem(m_dialogSaveLayout->IsTextAsPaths()); + QGraphicsItem *item = piece.GetItem(m_dialogSaveLayout->IsTextAsPaths(), + m_dialogSaveLayout->IsBoundaryTogetherWithNotches(), false); qreal diff = 0; if (piece.IsForceFlipping()) { const qreal x = item->boundingRect().x(); piece.Mirror(); delete item; - item = piece.GetItem(m_dialogSaveLayout->IsTextAsPaths()); + item = piece.GetItem(m_dialogSaveLayout->IsTextAsPaths(), + m_dialogSaveLayout->IsBoundaryTogetherWithNotches(), false); diff = item->boundingRect().x() - x; } @@ -1064,6 +1070,7 @@ void MainWindowsNoGUI::ExportScene(const QList &scenes, const exporter.SetIgnorePrinterMargins(ignorePrinterFields); exporter.SetBinaryDxfFormat(m_dialogSaveLayout->IsBinaryDXFFormat()); exporter.SetShowGrainline(m_dialogSaveLayout->IsShowGrainline()); + exporter.SetBoundaryTogetherWithNotches(m_dialogSaveLayout->IsBoundaryTogetherWithNotches()); for (int i = 0; i < scenes.size(); ++i) { diff --git a/src/app/valentina/xml/vpattern.cpp b/src/app/valentina/xml/vpattern.cpp index 6c46354b6..ea0939bad 100644 --- a/src/app/valentina/xml/vpattern.cpp +++ b/src/app/valentina/xml/vpattern.cpp @@ -1435,8 +1435,7 @@ void VPattern::ParsePointElement(VMainGraphicsScene *scene, QDomElement &domElem ParsePlaceLabel(domElement, parse); break; default: - VException e(tr("Unknown point type '%1'.").arg(type)); - throw e; + throw VException(tr("Unknown point type '%1'.").arg(type)); } } diff --git a/src/libs/ifc/schema.qrc b/src/libs/ifc/schema.qrc index dec7ba482..81fff7947 100644 --- a/src/libs/ifc/schema.qrc +++ b/src/libs/ifc/schema.qrc @@ -103,6 +103,7 @@ schema/layout/v0.1.4.xsd schema/layout/v0.1.5.xsd schema/layout/v0.1.6.xsd + schema/layout/v0.1.7.xsd schema/known_measurements/v1.0.0.xsd diff --git a/src/libs/ifc/schema/layout/v0.1.7.xsd b/src/libs/ifc/schema/layout/v0.1.7.xsd new file mode 100644 index 000000000..1652d8b54 --- /dev/null +++ b/src/libs/ifc/schema/layout/v0.1.7.xsd @@ -0,0 +1,590 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/libs/ifc/xml/vlayoutconverter.cpp b/src/libs/ifc/xml/vlayoutconverter.cpp index 6df412ce0..045967f56 100644 --- a/src/libs/ifc/xml/vlayoutconverter.cpp +++ b/src/libs/ifc/xml/vlayoutconverter.cpp @@ -45,8 +45,8 @@ using namespace Qt::Literals::StringLiterals; */ const QString VLayoutConverter::LayoutMinVerStr = QStringLiteral("0.1.0"); -const QString VLayoutConverter::LayoutMaxVerStr = QStringLiteral("0.1.6"); -const QString VLayoutConverter::CurrentSchema = QStringLiteral("://schema/layout/v0.1.6.xsd"); +const QString VLayoutConverter::LayoutMaxVerStr = QStringLiteral("0.1.7"); +const QString VLayoutConverter::CurrentSchema = QStringLiteral("://schema/layout/v0.1.7.xsd"); // VLayoutConverter::LayoutMinVer; // <== DON'T FORGET TO UPDATE TOO!!!! // VLayoutConverter::LayoutMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!! @@ -148,7 +148,8 @@ auto VLayoutConverter::XSDSchemas() -> QHash std::make_pair(FormatVersion(0, 1, 3), QStringLiteral("://schema/layout/v0.1.3.xsd")), std::make_pair(FormatVersion(0, 1, 4), QStringLiteral("://schema/layout/v0.1.4.xsd")), std::make_pair(FormatVersion(0, 1, 5), QStringLiteral("://schema/layout/v0.1.5.xsd")), - std::make_pair(FormatVersion(0, 1, 6), CurrentSchema), + std::make_pair(FormatVersion(0, 1, 6), QStringLiteral("://schema/layout/v0.1.6.xsd")), + std::make_pair(FormatVersion(0, 1, 7), CurrentSchema), }; return schemas; @@ -185,10 +186,11 @@ void VLayoutConverter::ApplyPatches() ToV0_1_5(); Q_FALLTHROUGH(); case (FormatVersion(0, 1, 5)): - ToV0_1_6(); + case (FormatVersion(0, 1, 6)): + ToV0_1_7(); ValidateXML(CurrentSchema); Q_FALLTHROUGH(); - case (FormatVersion(0, 1, 6)): + case (FormatVersion(0, 1, 7)): break; default: InvalidVersion(m_ver); @@ -400,11 +402,11 @@ void VLayoutConverter::ToV0_1_5() } //--------------------------------------------------------------------------------------------------------------------- -void VLayoutConverter::ToV0_1_6() +void VLayoutConverter::ToV0_1_7() { - // TODO. Delete if minimal supported version is 0.1.6 - Q_STATIC_ASSERT_X(VLayoutConverter::LayoutMinVer < FormatVersion(0, 1, 6), "Time to refactor the code."); + // TODO. Delete if minimal supported version is 0.1.7 + Q_STATIC_ASSERT_X(VLayoutConverter::LayoutMinVer < FormatVersion(0, 1, 7), "Time to refactor the code."); - SetVersion(QStringLiteral("0.1.6")); + SetVersion(QStringLiteral("0.1.7")); Save(); } diff --git a/src/libs/ifc/xml/vlayoutconverter.h b/src/libs/ifc/xml/vlayoutconverter.h index 563460bef..bc96ba530 100644 --- a/src/libs/ifc/xml/vlayoutconverter.h +++ b/src/libs/ifc/xml/vlayoutconverter.h @@ -47,7 +47,7 @@ public: static const QString LayoutMaxVerStr; static const QString CurrentSchema; static Q_DECL_CONSTEXPR const unsigned LayoutMinVer = FormatVersion(0, 1, 0); - static Q_DECL_CONSTEXPR const unsigned LayoutMaxVer = FormatVersion(0, 1, 6); + static Q_DECL_CONSTEXPR const unsigned LayoutMaxVer = FormatVersion(0, 1, 7); static auto XSDSchemas() -> QHash; @@ -74,7 +74,7 @@ protected: void ToV0_1_3(); void ToV0_1_5(); - void ToV0_1_6(); + void ToV0_1_7(); private: Q_DISABLE_COPY_MOVE(VLayoutConverter) // NOLINT diff --git a/src/libs/vdxf/vdxfengine.cpp b/src/libs/vdxf/vdxfengine.cpp index 9d4781ad4..160848e84 100644 --- a/src/libs/vdxf/vdxfengine.cpp +++ b/src/libs/vdxf/vdxfengine.cpp @@ -54,7 +54,9 @@ #include "../vgeometry/vgeometrydef.h" #include "../vgeometry/vlayoutplacelabel.h" +#include "../vlayout/vboundary.h" #include "../vlayout/vlayoutpiece.h" +#include "../vlayout/vlayoutpiecepath.h" #include "../vlayout/vlayoutpoint.h" #include "../vmisc/def.h" #include "dxiface.h" @@ -654,6 +656,19 @@ void VDxfEngine::SetYScale(const qreal &yscale) m_yscale = yscale; } +//--------------------------------------------------------------------------------------------------------------------- +void VDxfEngine::SetBoundaryTogetherWithNotches(bool value) +{ + Q_ASSERT(not isActive()); + m_togetherWithNotches = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VDxfEngine::IsBoundaryTogetherWithNotches() const -> bool +{ + return m_togetherWithNotches; +} + //--------------------------------------------------------------------------------------------------------------------- auto VDxfEngine::ErrorString() const -> QString { @@ -768,6 +783,28 @@ void VDxfEngine::ExportAAMAOutline(const QSharedPointer &detailBl { QVector points = PieceOutline(detail); + if (m_togetherWithNotches) + { + const QVector passmarks = detail.GetMappedPassmarks(); + + bool seamAllowance = detail.IsSeamAllowance() && !detail.IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + + VBoundary boundary(points, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(detail.GetName()); + const QList sequence = boundary.Combine(passmarks, false, false); + + points.clear(); + + for (const auto &item : sequence) + { + const auto path = item.item.value().Points(); + points += path; + } + + points = VAbstractPiece::RemoveDublicates(points, false); + } + if (DRW_Entity *e = AAMAPolygon(points, *layer1, true)) { detailBlock->ent.push_back(e); @@ -780,19 +817,7 @@ void VDxfEngine::ExportAAMAOutline(const QSharedPointer &detailBl //--------------------------------------------------------------------------------------------------------------------- void VDxfEngine::ExportAAMADraw(const QSharedPointer &detailBlock, const VLayoutPiece &detail) { - if (detail.IsSeamAllowance() && not detail.IsHideMainPath() && not detail.IsSeamAllowanceBuiltIn()) - { - QVector points = detail.GetMappedContourPoints(); - const UTF8STRING &layer = not detail.IsSewLineOnDrawing() ? *layer14 : *layer8; - - if (DRW_Entity *e = AAMAPolygon(points, layer, true)) - { - detailBlock->ent.push_back(e); - } - - ExportTurnPoints(detailBlock, points); - ExportCurvePoints(detailBlock, points); - } + ExportAAMADrawSewLine(detailBlock, detail); const QVector> drawIntLine = detail.MappedInternalPathsForCut(false); for (const auto &intLine : drawIntLine) @@ -827,6 +852,49 @@ void VDxfEngine::ExportAAMADraw(const QSharedPointer &detailBlock } } +//--------------------------------------------------------------------------------------------------------------------- +void VDxfEngine::ExportAAMADrawSewLine(const QSharedPointer &detailBlock, const VLayoutPiece &detail) +{ + if (detail.IsSeamAllowance() && not detail.IsHideMainPath() && not detail.IsSeamAllowanceBuiltIn()) + { + const UTF8STRING &layer = not detail.IsSewLineOnDrawing() ? *layer14 : *layer8; + QVector points = detail.GetMappedContourPoints(); + + auto DrawPolygon = [this, detailBlock, layer](const QVector &points, bool forceClosed) + { + if (DRW_Entity *e = AAMAPolygon(points, layer, forceClosed)) + { + detailBlock->ent.push_back(e); + } + + ExportTurnPoints(detailBlock, points); + ExportCurvePoints(detailBlock, points); + }; + + if (m_togetherWithNotches) + { + const QVector passmarks = detail.GetMappedPassmarks(); + + bool seamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + + VBoundary boundary(points, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(detail.GetName()); + const QList sequence = boundary.Combine(passmarks, true, false); + + for (const auto &item : sequence) + { + const auto path = item.item.value().Points(); + DrawPolygon(path, false); + } + } + else + { + DrawPolygon(points, true); + } + } +} + //--------------------------------------------------------------------------------------------------------------------- void VDxfEngine::ExportAAMAIntcut(const QSharedPointer &detailBlock, const VLayoutPiece &detail) { @@ -846,7 +914,7 @@ void VDxfEngine::ExportAAMAIntcut(const QSharedPointer &detailBlo //--------------------------------------------------------------------------------------------------------------------- void VDxfEngine::ExportAAMANotch(const QSharedPointer &detailBlock, const VLayoutPiece &detail) { - if (detail.IsSeamAllowance()) + if (detail.IsSeamAllowance() && !m_togetherWithNotches) { const QVector passmarks = detail.GetMappedPassmarks(); for (const auto &passmark : passmarks) @@ -1001,6 +1069,28 @@ void VDxfEngine::ExportASTMPieceBoundary(const QSharedPointer &de { QVector pieceBoundary = PieceOutline(detail); + if (m_togetherWithNotches) + { + const QVector passmarks = detail.GetMappedPassmarks(); + + bool seamAllowance = detail.IsSeamAllowance() && !detail.IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + + VBoundary boundary(pieceBoundary, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(detail.GetName()); + const QList sequence = boundary.Combine(passmarks, false, false); + + pieceBoundary.clear(); + + for (const auto &item : sequence) + { + const auto path = item.item.value().Points(); + pieceBoundary += path; + } + + pieceBoundary = VAbstractPiece::RemoveDublicates(pieceBoundary, false); + } + // Piece boundary if (DRW_Entity *e = AAMAPolygon(pieceBoundary, *layer1, true)) { @@ -1024,19 +1114,44 @@ void VDxfEngine::ExportASTMSewLine(const QSharedPointer &detailBl { QVector sewLine = detail.GetMappedContourPoints(); - // Sew lines - if (DRW_Entity *e = AAMAPolygon(sewLine, *layer14, true)) + auto DrawPolygon = [this, detailBlock](const QVector &points, bool forceClosed) { - detailBlock->ent.push_back(e); + // Sew lines + if (DRW_Entity *e = AAMAPolygon(points, *layer14, forceClosed)) + { + detailBlock->ent.push_back(e); + } + + ExportTurnPoints(detailBlock, points); + ExportCurvePoints(detailBlock, points); + + // Sew lines quality validation curves + if (DRW_Entity *e = AAMAPolygon(points, *layer87, forceClosed)) + { + detailBlock->ent.push_back(e); + } + }; + + if (m_togetherWithNotches) + { + const QVector passmarks = detail.GetMappedPassmarks(); + + bool seamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + + VBoundary boundary(sewLine, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(detail.GetName()); + const QList sequence = boundary.Combine(passmarks, true, false); + + for (const auto &item : sequence) + { + const auto path = item.item.value().Points(); + DrawPolygon(path, false); + } } - - ExportTurnPoints(detailBlock, sewLine); - ExportCurvePoints(detailBlock, sewLine); - - // Sew lines quality validation curves - if (DRW_Entity *e = AAMAPolygon(sewLine, *layer87, true)) + else { - detailBlock->ent.push_back(e); + DrawPolygon(sewLine, true); } } } @@ -1154,7 +1269,7 @@ void VDxfEngine::ExportASTMDrill(const QSharedPointer &detailBloc //--------------------------------------------------------------------------------------------------------------------- void VDxfEngine::ExportASTMNotches(const QSharedPointer &detailBlock, const VLayoutPiece &detail) { - if (!detail.IsSeamAllowance()) + if (!detail.IsSeamAllowance() || m_togetherWithNotches) { return; } diff --git a/src/libs/vdxf/vdxfengine.h b/src/libs/vdxf/vdxfengine.h index 51312806a..0b84439f9 100644 --- a/src/libs/vdxf/vdxfengine.h +++ b/src/libs/vdxf/vdxfengine.h @@ -113,6 +113,9 @@ public: auto GetYScale() const -> qreal; void SetYScale(const qreal &yscale); + void SetBoundaryTogetherWithNotches(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + auto ErrorString() const -> QString; private: @@ -130,6 +133,7 @@ private: DRW_Text *m_textBuffer{nullptr}; qreal m_xscale{1}; qreal m_yscale{1}; + bool m_togetherWithNotches{false}; Q_REQUIRED_RESULT auto FromPixel(double pix, const VarInsunits &unit) const -> double; Q_REQUIRED_RESULT auto ToPixel(double val, const VarInsunits &unit) const -> double; @@ -137,6 +141,7 @@ private: auto ExportToAAMA(const QVector &details) -> bool; void ExportAAMAOutline(const QSharedPointer &detailBlock, const VLayoutPiece &detail); void ExportAAMADraw(const QSharedPointer &detailBlock, const VLayoutPiece &detail); + void ExportAAMADrawSewLine(const QSharedPointer &detailBlock, const VLayoutPiece &detail); void ExportAAMAIntcut(const QSharedPointer &detailBlock, const VLayoutPiece &detail); void ExportAAMANotch(const QSharedPointer &detailBlock, const VLayoutPiece &detail); void ExportAAMAGrainline(const QSharedPointer &detailBlock, const VLayoutPiece &detail); diff --git a/src/libs/vdxf/vdxfpaintdevice.cpp b/src/libs/vdxf/vdxfpaintdevice.cpp index 379d1bd93..812d5bc2b 100644 --- a/src/libs/vdxf/vdxfpaintdevice.cpp +++ b/src/libs/vdxf/vdxfpaintdevice.cpp @@ -196,6 +196,24 @@ void VDxfPaintDevice::SetYScale(const qreal &yscale) m_engine->SetYScale(yscale); } +//--------------------------------------------------------------------------------------------------------------------- +void VDxfPaintDevice::SetBoundaryTogetherWithNotches(bool value) +{ + if (m_engine->isActive()) + { + qWarning("VDxfPaintDevice::SetBoundaryTogetherWithNotches(), cannot set boundary together with notches while " + "Dxf is being generated"); + return; + } + m_engine->SetBoundaryTogetherWithNotches(value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VDxfPaintDevice::IsBoundaryTogetherWithNotches() const -> bool +{ + return m_engine->IsBoundaryTogetherWithNotches(); +} + //--------------------------------------------------------------------------------------------------------------------- auto VDxfPaintDevice::ExportToAAMA(const QVector &details) const -> bool { diff --git a/src/libs/vdxf/vdxfpaintdevice.h b/src/libs/vdxf/vdxfpaintdevice.h index 592a69308..0579b07db 100644 --- a/src/libs/vdxf/vdxfpaintdevice.h +++ b/src/libs/vdxf/vdxfpaintdevice.h @@ -72,6 +72,9 @@ public: auto GetYScale() const -> qreal; void SetYScale(const qreal &yscale); + void SetBoundaryTogetherWithNotches(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + auto ExportToAAMA(const QVector &details) const -> bool; auto ExportToASTM(const QVector &details) const -> bool; diff --git a/src/libs/vgeometry/vabstractcurve.cpp b/src/libs/vgeometry/vabstractcurve.cpp index 30221133f..c25ad1c7a 100644 --- a/src/libs/vgeometry/vabstractcurve.cpp +++ b/src/libs/vgeometry/vabstractcurve.cpp @@ -415,74 +415,6 @@ auto VAbstractCurve::IsPointOnCurve(const QPointF &p) const -> bool return IsPointOnCurve(GetPoints(), p); } -//--------------------------------------------------------------------------------------------------------------------- -auto VAbstractCurve::SubdividePath(const QVector &points, QPointF p, QVector &sub1, - QVector &sub2) -> bool -{ - if (points.size() < 2) - { - return false; - } - - bool found = false; - sub1.clear(); - sub2.clear(); - - for (qint32 i = 0; i < points.count() - 1; ++i) - { - if (not found) - { - if (IsPointOnLineSegment(p, points.at(i), points.at(i + 1))) - { - if (not VFuzzyComparePoints(points.at(i), p)) - { - sub1.append(points.at(i)); - sub1.append(p); - } - else - { - if (not sub1.isEmpty()) - { - sub1.append(p); - } - } - - if (not VFuzzyComparePoints(points.at(i + 1), p)) - { - sub2.append(p); - - if (i + 1 == points.count() - 1) - { - sub2.append(points.at(i + 1)); - } - } - - found = true; - } - else - { - sub1.append(points.at(i)); - } - } - else - { - sub2.append(points.at(i)); - - if (i + 1 == points.count() - 1) - { - sub2.append(points.at(i + 1)); - } - } - } - - if (not found) - { - sub1.clear(); - } - - return found; -} - //--------------------------------------------------------------------------------------------------------------------- auto VAbstractCurve::GetDuplicate() const -> quint32 { diff --git a/src/libs/vgeometry/vabstractcurve.h b/src/libs/vgeometry/vabstractcurve.h index fbecd6c5e..0c40f0109 100644 --- a/src/libs/vgeometry/vabstractcurve.h +++ b/src/libs/vgeometry/vabstractcurve.h @@ -78,9 +78,6 @@ public: static auto IsPointOnCurve(const QVector &points, const QPointF &p) -> bool; auto IsPointOnCurve(const QPointF &p) const -> bool; - static auto SubdividePath(const QVector &points, QPointF p, QVector &sub1, QVector &sub2) - -> bool; - auto ClosestPoint(QPointF scenePoint) const -> QPointF; virtual auto GetStartAngle() const -> qreal = 0; diff --git a/src/libs/vgeometry/vgeometrydef.cpp b/src/libs/vgeometry/vgeometrydef.cpp index cb0959889..1f9485a89 100644 --- a/src/libs/vgeometry/vgeometrydef.cpp +++ b/src/libs/vgeometry/vgeometrydef.cpp @@ -43,7 +43,7 @@ using namespace Qt::Literals::StringLiterals; const quint32 VLayoutPassmark::streamHeader = 0x943E2759; // CRC-32Q string "VLayoutPassmark" -const quint16 VLayoutPassmark::classVersion = 2; +const quint16 VLayoutPassmark::classVersion = 3; // Friend functions //--------------------------------------------------------------------------------------------------------------------- @@ -51,7 +51,7 @@ auto operator<<(QDataStream &dataStream, const VLayoutPassmark &data) -> QDataSt { dataStream << VLayoutPassmark::streamHeader << VLayoutPassmark::classVersion; - dataStream << data.lines << data.type << data.baseLine << data.isBuiltIn << data.isClockwiseOpening; + dataStream << data.lines << data.type << data.baseLine << data.isBuiltIn << data.isClockwiseOpening << data.label; return dataStream; } @@ -89,5 +89,10 @@ auto operator>>(QDataStream &dataStream, VLayoutPassmark &data) -> QDataStream & dataStream >> data.isClockwiseOpening; } + if (actualClassVersion >= 3) + { + dataStream >> data.label; + } + return dataStream; } diff --git a/src/libs/vgeometry/vgeometrydef.h b/src/libs/vgeometry/vgeometrydef.h index 319240f87..03944b75a 100644 --- a/src/libs/vgeometry/vgeometrydef.h +++ b/src/libs/vgeometry/vgeometrydef.h @@ -29,9 +29,9 @@ #ifndef VGEOMETRYDEF_H #define VGEOMETRYDEF_H -#include #include #include +#include #include "../vmisc/def.h" @@ -47,12 +47,16 @@ enum class GOType : qint8 PlaceLabel, Unknown }; -enum class SplinePointPosition : qint8 { FirstPoint, LastPoint }; +enum class SplinePointPosition : qint8 +{ + FirstPoint, + LastPoint +}; // Keep synchronized with XSD schema -enum class PlaceLabelType : quint8 +enum class PlaceLabelType : quint8 { - Segment= 0, + Segment = 0, Rectangle = 1, Cross = 2, Tshaped = 3, @@ -71,9 +75,11 @@ struct VLayoutPassmark QLineF baseLine{}; bool isBuiltIn{false}; bool isClockwiseOpening{false}; + QString label{}; + + friend auto operator<<(QDataStream &dataStream, const VLayoutPassmark &data) -> QDataStream &; + friend auto operator>>(QDataStream &dataStream, VLayoutPassmark &data) -> QDataStream &; - friend auto operator<<(QDataStream& dataStream, const VLayoutPassmark& data) -> QDataStream&; - friend auto operator>>(QDataStream& dataStream, VLayoutPassmark& data) -> QDataStream&; private: static const quint32 streamHeader; static const quint16 classVersion; diff --git a/src/libs/vhpgl/vhpglengine.cpp b/src/libs/vhpgl/vhpglengine.cpp index c8192b792..f7ab713b7 100644 --- a/src/libs/vhpgl/vhpglengine.cpp +++ b/src/libs/vhpgl/vhpglengine.cpp @@ -29,6 +29,7 @@ #include "../vformat/vsinglelineoutlinechar.h" #include "../vgeometry/vlayoutplacelabel.h" +#include "../vlayout/vboundary.h" #include "../vlayout/vlayoutpiece.h" #include "../vlayout/vlayoutpiecepath.h" #include "../vlayout/vlayoutpoint.h" @@ -39,7 +40,6 @@ #include "../vmisc/svgfont/vsvgfontdatabase.h" #include "../vmisc/svgfont/vsvgfontengine.h" #include "../vmisc/vabstractapplication.h" -#include "qmath.h" #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) #include "../vmisc/backport/text.h" @@ -57,8 +57,6 @@ using namespace Qt::Literals::StringLiterals; namespace { -const qreal accuracyPointOnLine{0.99}; - QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wunused-member-function") @@ -83,92 +81,6 @@ Q_DECL_RELAXED_CONSTEXPR inline auto ConvertPixels(qreal pix) -> qreal return FromPixel(pix, Unit::Mm) * 40.; } -//--------------------------------------------------------------------------------------------------------------------- -auto RemoveDublicates(QVector points) -> QVector -{ - if (points.size() < 3) - { - return points; - } - - for (int i = 0; i < points.size() - 1; ++i) - { - if (points.at(i) == points.at(i + 1)) - { -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - points.erase(points.cbegin() + i + 1); -#else - points.erase(points.begin() + i + 1); -#endif - --i; - } - } - - return points; -} - -//--------------------------------------------------------------------------------------------------------------------- -auto OptimizePath(QVector path) -> QVector -{ - if (path.size() < 3) - { - return path; - } - - path = RemoveDublicates(path); - - if (path.size() < 3) - { - return path; - } - - vsizetype prev = -1; - const bool closedPath = (path.first() == path.last()); - const vsizetype startIndex = closedPath ? 0 : 1; - const vsizetype endIndex = closedPath ? path.size() : path.size() - 1; - - QVector cleared; - cleared.reserve(path.size()); - - if (!closedPath) - { - cleared.append(path.first()); - } - - // Remove point on line - for (vsizetype i = startIndex; i < endIndex; ++i) - { - if (prev == -1) - { - prev = (i == 0) ? path.size() - 1 : i - 1; - } - - const vsizetype next = (i == path.size() - 1) ? 0 : i + 1; - - const QPoint &iPoint = path.at(i); - const QPoint &prevPoint = path.at(prev); - const QPoint &nextPoint = path.at(next); - - // If RemoveDublicates does not remove these points it is a valid case. - // Case where last point equal first point - if (((i == 0 || i == path.size() - 1) && (iPoint == prevPoint || iPoint == nextPoint)) || - not VGObject::IsPointOnLineviaPDP(iPoint, prevPoint, nextPoint, accuracyPointOnLine)) - { - cleared.append(iPoint); - prev = -1; - } - } - - if (!closedPath) - { - cleared.append(path.last()); - } - - cleared = RemoveDublicates(cleared); - - return cleared; -} - //--------------------------------------------------------------------------------------------------------------------- template inline auto CastToPoint(const QVector &points) -> QVector { @@ -464,7 +376,7 @@ void VHPGLEngine::ExportDetails(QTextStream &out, const QList &det detail.Scale(m_xscale, m_yscale); PlotSeamAllowance(out, detail); - PlotMainPath(out, detail); + PlotSewLine(out, detail); PlotInternalPaths(out, detail); PlotGrainline(out, detail); PlotPlaceLabels(out, detail); @@ -482,13 +394,72 @@ void VHPGLEngine::GenerateHPGLFooter(QTextStream &out) } //--------------------------------------------------------------------------------------------------------------------- -void VHPGLEngine::PlotMainPath(QTextStream &out, const VLayoutPiece &detail) +void VHPGLEngine::PlotSewLine(QTextStream &out, const VLayoutPiece &detail) { - if (not detail.IsSeamAllowance() || - (detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn() && not detail.IsHideMainPath())) + if (detail.IsSeamAllowance() && not detail.IsHideMainPath() && not detail.IsSeamAllowanceBuiltIn()) { - QVector points = CastToPoint(ConvertPath(detail.GetMappedContourPoints())); + QVector sewLine = detail.GetMappedContourPoints(); + if (m_togetherWithNotches) + { + const QVector passmarks = detail.GetMappedPassmarks(); + + bool seamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + + VBoundary boundary(sewLine, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(detail.GetName()); + const QList sequence = boundary.Combine(passmarks, true, false); + + for (const auto &item : sequence) + { + const auto path = CastToPoint(ConvertPath(item.item.value().Points())); + PlotPath(out, path, Qt::SolidLine); + } + } + else + { + QVector points = CastToPoint(ConvertPath(sewLine)); + + if (points.size() > 1 && points.first() != points.last()) + { + points.append(points.first()); // must be closed + } + + PlotPath(out, points, Qt::SolidLine); + } + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLEngine::PlotSeamAllowance(QTextStream &out, const VLayoutPiece &detail) +{ + QVector pieceBoundary = detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn() + ? detail.GetMappedSeamAllowancePoints() + : detail.GetMappedContourPoints(); + + if (m_togetherWithNotches) + { + const QVector passmarks = detail.GetMappedPassmarks(); + + bool seamAllowance = detail.IsSeamAllowance() && !detail.IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + + VBoundary boundary(pieceBoundary, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(detail.GetName()); + const QList sequence = boundary.Combine(passmarks, false, false); + + pieceBoundary.clear(); + + for (const auto &item : sequence) + { + const auto path = CastToPoint(ConvertPath(item.item.value().Points())); + PlotPath(out, path, Qt::SolidLine); + } + } + else + { + QVector points = CastToPoint(ConvertPath(pieceBoundary)); if (points.size() > 1 && points.first() != points.last()) { points.append(points.first()); // must be closed @@ -498,21 +469,6 @@ void VHPGLEngine::PlotMainPath(QTextStream &out, const VLayoutPiece &detail) } } -//--------------------------------------------------------------------------------------------------------------------- -void VHPGLEngine::PlotSeamAllowance(QTextStream &out, const VLayoutPiece &detail) -{ - QVector points = detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn() - ? CastToPoint(ConvertPath(detail.GetMappedSeamAllowancePoints())) - : CastToPoint(ConvertPath(detail.GetMappedContourPoints())); - - if (points.size() > 1 && points.first() != points.last()) - { - points.append(points.first()); // must be closed - } - - PlotPath(out, points, Qt::SolidLine); -} - //--------------------------------------------------------------------------------------------------------------------- void VHPGLEngine::PlotInternalPaths(QTextStream &out, const VLayoutPiece &detail) { @@ -541,6 +497,11 @@ void VHPGLEngine::PlotPlaceLabels(QTextStream &out, const VLayoutPiece &detail) //--------------------------------------------------------------------------------------------------------------------- void VHPGLEngine::PlotPassmarks(QTextStream &out, const VLayoutPiece &detail) { + if (m_togetherWithNotches) + { + return; + } + const QVector passmarks = detail.GetMappedPassmarks(); for (const auto &passmark : passmarks) { @@ -710,7 +671,6 @@ void VHPGLEngine::PlotLabelOutlineFont(QTextStream &out, const VLayoutPiece &det } //--------------------------------------------------------------------------------------------------------------------- - template auto VHPGLEngine::ConvertPath(const QVector &path) const -> QVector { QVector convertedPath; @@ -740,8 +700,6 @@ void VHPGLEngine::PlotPath(QTextStream &out, QVector path, Qt::PenStyle return; } - path = OptimizePath(path); - if (penStyle != Qt::SolidLine && penStyle != Qt::DashLine && penStyle != Qt::DotLine && penStyle != Qt::DashDotLine && penStyle != Qt::DashDotDotLine) { diff --git a/src/libs/vhpgl/vhpglengine.h b/src/libs/vhpgl/vhpglengine.h index 1a440ec63..044f7fd82 100644 --- a/src/libs/vhpgl/vhpglengine.h +++ b/src/libs/vhpgl/vhpglengine.h @@ -80,6 +80,9 @@ public: auto GetYScale() const -> qreal; void SetYScale(const qreal &yscale); + void SetBoundaryTogetherWithNotches(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + void SetIsertNewLine(bool insert); static auto SortDetails(const QVector &details) -> QList; @@ -101,6 +104,7 @@ private: qreal m_xscale{1}; qreal m_yscale{1}; bool m_showGrainline{true}; + bool m_togetherWithNotches{false}; auto GenerateHPGL(const QVector &details) -> bool; auto GenerateHPGL2(const QVector &details) -> bool; @@ -110,7 +114,7 @@ private: void ExportDetails(QTextStream &out, const QList &details); void GenerateHPGLFooter(QTextStream &out); - void PlotMainPath(QTextStream &out, const VLayoutPiece &detail); + void PlotSewLine(QTextStream &out, const VLayoutPiece &detail); void PlotSeamAllowance(QTextStream &out, const VLayoutPiece &detail); void PlotInternalPaths(QTextStream &out, const VLayoutPiece &detail); void PlotPlaceLabels(QTextStream &out, const VLayoutPiece &detail); @@ -263,4 +267,17 @@ inline void VHPGLEngine::SetShowGrainline(bool newShowGrainline) m_showGrainline = newShowGrainline; } +//--------------------------------------------------------------------------------------------------------------------- +inline void VHPGLEngine::SetBoundaryTogetherWithNotches(bool value) +{ + Q_ASSERT(not isActive()); + m_togetherWithNotches = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VHPGLEngine::IsBoundaryTogetherWithNotches() const -> bool +{ + return m_togetherWithNotches; +} + #endif // VHPGLENGINE_H diff --git a/src/libs/vhpgl/vhpglpaintdevice.cpp b/src/libs/vhpgl/vhpglpaintdevice.cpp index 8c73798de..14c2f3ce7 100644 --- a/src/libs/vhpgl/vhpglpaintdevice.cpp +++ b/src/libs/vhpgl/vhpglpaintdevice.cpp @@ -199,3 +199,21 @@ void VHPGLPaintDevice::SetShowGrainline(bool newShowGrainline) } m_engine->SetShowGrainline(newShowGrainline); } + +//--------------------------------------------------------------------------------------------------------------------- +void VHPGLPaintDevice::SetBoundaryTogetherWithNotches(bool value) +{ + if (m_engine->isActive()) + { + qWarning("VHPGLPaintDevice::SetBoundaryTogetherWithNotches(), cannot set boundary together with notches while " + "HPGL is being generated"); + return; + } + m_engine->SetBoundaryTogetherWithNotches(value); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VHPGLPaintDevice::IsBoundaryTogetherWithNotches() const -> bool +{ + return m_engine->IsBoundaryTogetherWithNotches(); +} diff --git a/src/libs/vhpgl/vhpglpaintdevice.h b/src/libs/vhpgl/vhpglpaintdevice.h index 7c481f976..2883f4a33 100644 --- a/src/libs/vhpgl/vhpglpaintdevice.h +++ b/src/libs/vhpgl/vhpglpaintdevice.h @@ -68,6 +68,9 @@ public: auto GetShowGrainline() const -> bool; void SetShowGrainline(bool newShowGrainline); + void SetBoundaryTogetherWithNotches(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + auto ExportToHPGL(const QVector &details) const -> bool; auto ExportToHPGL2(const QVector &details) const -> bool; diff --git a/src/libs/vlayout/vabstractpiece.cpp b/src/libs/vlayout/vabstractpiece.cpp index 110edd6ff..6ad1338d3 100644 --- a/src/libs/vlayout/vabstractpiece.cpp +++ b/src/libs/vlayout/vabstractpiece.cpp @@ -37,14 +37,14 @@ #include "../vpatterndb/floatItemData/vgrainlinedata.h" #include "../vpatterndb/vcontainer.h" #include "../vwidgets/vpiecegrainline.h" -#include "qline.h" -#include "qmath.h" #include "vabstractpiece_p.h" +#include "vlayoutpiecepath.h" #include "vrawsapoint.h" #include #include #include +#include #include #include #include diff --git a/src/libs/vlayout/vabstractpiece.h b/src/libs/vlayout/vabstractpiece.h index 16ccb2bb9..5ef9ce124 100644 --- a/src/libs/vlayout/vabstractpiece.h +++ b/src/libs/vlayout/vabstractpiece.h @@ -139,9 +139,10 @@ public: static auto LabelShapePath(const VLayoutPlaceLabel &label) -> QPainterPath; static auto LabelShapePath(const PlaceLabelImg &shape) -> QPainterPath; -protected: template static auto RemoveDublicates(const QVector &points, bool removeFirstAndLast = true) -> QVector; + +protected: static auto IsEkvPointOnLine(const QPointF &iPoint, const QPointF &prevPoint, const QPointF &nextPoint) -> bool; static auto IsEkvPointOnLine(const VSAPoint &iPoint, const VSAPoint &prevPoint, const VSAPoint &nextPoint) -> bool; template diff --git a/src/libs/vlayout/vbank.cpp b/src/libs/vlayout/vbank.cpp index 9bd3ac737..4e16a126b 100644 --- a/src/libs/vlayout/vbank.cpp +++ b/src/libs/vlayout/vbank.cpp @@ -28,13 +28,13 @@ #include "vbank.h" -#include #include +#include -#include "../vmisc/vabstractvalapplication.h" -#include "../vmisc/compatibility.h" -#include "vlayoutdef.h" #include "../ifc/exception/vexception.h" +#include "../vmisc/compatibility.h" +#include "../vmisc/vabstractvalapplication.h" +#include "vlayoutdef.h" QT_WARNING_PUSH QT_WARNING_DISABLE_CLANG("-Wmissing-prototypes") @@ -47,7 +47,7 @@ QT_WARNING_POP // An annoying char define, from the Windows team in // #define small char // http://stuartjames.info/Journal/c--visual-studio-2012-vs2012--win8--converting-projects-up-some-conflicts-i-found.aspx -#if defined (Q_OS_WIN) && defined (Q_CC_MSVC) +#if defined(Q_OS_WIN) && defined(Q_CC_MSVC) #pragma push_macro("small") #undef small #endif @@ -160,11 +160,12 @@ auto TakeFirstForPriority(const QMap> &container, uint return -1; } -} +} // namespace //--------------------------------------------------------------------------------------------------------------------- VBank::VBank() -{} +{ +} //--------------------------------------------------------------------------------------------------------------------- auto VBank::GetLayoutWidth() const -> qreal @@ -245,7 +246,7 @@ auto VBank::GetNext() -> int } }; - for (auto &group: groups) + for (auto &group : groups) { int next = -1; if (group != 0) // Group 0 must go last @@ -327,14 +328,14 @@ auto VBank::PrepareUnsorted() -> bool { QSet uniqueGroup; - for (int i=0; i < details.size(); ++i) + for (int i = 0; i < details.size(); ++i) { const qint64 square = details.at(i).Square(); if (square <= 0) { - qCCritical(lBank) << VAbstractValApplication::warningMessageSignature + - tr("Error of preparing data for layout: Detail '%1' square <= 0") - .arg(details.at(i).GetName()); + qCCritical(lBank) + << VAbstractValApplication::warningMessageSignature + + tr("Error of preparing data for layout: Detail '%1' square <= 0").arg(details.at(i).GetName()); prepare = false; return prepare; } @@ -353,7 +354,7 @@ auto VBank::PrepareUnsorted() -> bool } //--------------------------------------------------------------------------------------------------------------------- -auto VBank::PrepareDetails() -> bool +auto VBank::PrepareDetails(bool togetherWithNotches) -> bool { if (layoutWidth <= 0) { @@ -378,20 +379,22 @@ auto VBank::PrepareDetails() -> bool diagonal = 0; - for (int i=0; i < details.size(); ++i) + for (auto &detail : details) { - details[i].SetLayoutWidth(layoutWidth); - details[i].SetLayoutAllowancePoints(); + detail.SetLayoutWidth(layoutWidth); + detail.SetLayoutAllowancePoints(togetherWithNotches); - if (not details.at(i).IsLayoutAllowanceValid()) + if (not detail.IsLayoutAllowanceValid(togetherWithNotches)) { const QString errorMsg = QObject::tr("Piece '%1' has invalid layout allowance. Please, check seam allowance" - " to check how seam allowance behave.").arg(details.at(i).GetName()); - VAbstractApplication::VApp()->IsPedantic() ? throw VException(errorMsg) : - qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg; + " to check how seam allowance behave.") + .arg(detail.GetName()); + VAbstractApplication::VApp()->IsPedantic() + ? throw VException(errorMsg) + : qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg; } - const qreal d = details.at(i).Diagonal(); + const qreal d = detail.Diagonal(); if (d > diagonal) { diagonal = d; @@ -478,8 +481,8 @@ void VBank::PrepareThreeGroups(uint priority) SqMaxMin(sMax, sMin, priority); - const qint64 s1 = sMax - (sMax - sMin)/3; - const qint64 s2 = sMin + (sMax - sMin)/3; + const qint64 s1 = sMax - (sMax - sMin) / 3; + const qint64 s2 = sMin + (sMax - sMin) / 3; const QHash usortedGroup = unsorted.value(priority); QHash::const_iterator i = usortedGroup.constBegin(); @@ -510,7 +513,7 @@ void VBank::PrepareTwoGroups(uint priority) SqMaxMin(sMax, sMin, priority); - const qint64 s = (sMax + sMin)/2; + const qint64 s = (sMax + sMin) / 2; const QHash usortedGroup = unsorted.value(priority); QHash::const_iterator i = usortedGroup.constBegin(); while (i != usortedGroup.constEnd()) @@ -683,7 +686,6 @@ auto VBank::IsRotationNeeded() const -> bool return false; } - -#if defined (Q_OS_WIN) && defined (Q_CC_MSVC) +#if defined(Q_OS_WIN) && defined(Q_CC_MSVC) #pragma pop_macro("small") #endif diff --git a/src/libs/vlayout/vbank.h b/src/libs/vlayout/vbank.h index 04cac4bd5..6d96c4eae 100644 --- a/src/libs/vlayout/vbank.h +++ b/src/libs/vlayout/vbank.h @@ -30,31 +30,33 @@ #define VBANK_H #include +#include #include #include #include #include -#include #include "../vmisc/typedef.h" -#include "vlayoutpiece.h" #include "vlayoutdef.h" +#include "vlayoutpiece.h" // An annoying char define, from the Windows team in // #define small char // http://stuartjames.info/Journal/c--visual-studio-2012-vs2012--win8--converting-projects-up-some-conflicts-i-found.aspx -#if defined (Q_OS_WIN) && defined (Q_CC_MSVC) +#if defined(Q_OS_WIN) && defined(Q_CC_MSVC) #pragma push_macro("small") #undef small #endif -Q_DECLARE_LOGGING_CATEGORY(lBank) +Q_DECLARE_LOGGING_CATEGORY(lBank) // NOLINT class VBank { Q_DECLARE_TR_FUNCTIONS(VBank) // NOLINT + public: VBank(); + ~VBank() = default; auto GetLayoutWidth() const -> qreal; void SetLayoutWidth(qreal value); @@ -73,7 +75,7 @@ public: void NotArranged(int i); auto PrepareUnsorted() -> bool; - auto PrepareDetails() -> bool; + auto PrepareDetails(bool togetherWithNotches) -> bool; void Reset(); void SetCaseType(Cases caseType); @@ -122,7 +124,7 @@ private: auto ArrangedDetail(QMap> &container, int i) -> bool; }; -#if defined (Q_OS_WIN) && defined (Q_CC_MSVC) +#if defined(Q_OS_WIN) && defined(Q_CC_MSVC) #pragma pop_macro("small") #endif diff --git a/src/libs/vlayout/vboundary.cpp b/src/libs/vlayout/vboundary.cpp new file mode 100644 index 000000000..8a7322263 --- /dev/null +++ b/src/libs/vlayout/vboundary.cpp @@ -0,0 +1,644 @@ +/************************************************************************ + ** + ** @file vboundary.cpp + ** @author Roman Telezhynskyi + ** @date 24 11, 2023 + ** + ** @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) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#include "vboundary.h" +#include "../ifc/exception/vexception.h" +#include "../vgeometry/vgobject.h" +#include "../vmisc/vabstractapplication.h" +#include "vlayoutpiecepath.h" + +#include + +#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0) +#include "../vmisc/compatibility.h" +#endif + +using namespace Qt::Literals::StringLiterals; + +namespace +{ +//--------------------------------------------------------------------------------------------------------------------- +void FillSequance(VBoundarySequenceItemData itemData, QList &sequence) +{ + if (itemData.number <= 0) + { + itemData.number = 0; + sequence.append(itemData); + } + else if (sequence.isEmpty()) + { + sequence.append(itemData); + } + else + { + for (int i = 0; i < sequence.size(); ++i) + { + if (sequence.at(i).number > itemData.number || sequence.at(i).number == 0) + { + sequence.insert(i, itemData); + return; + } + } + + sequence.append(itemData); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PrepareSequenceItem(const QVector &path, bool drawMode, VBoundarySequenceItem type) + -> VBoundarySequenceItemData +{ + VLayoutPiecePath countur(path); + countur.SetCutPath(!drawMode); + + VBoundarySequenceItemData itemData; + itemData.item = QVariant::fromValue(countur); + itemData.type = type; + + return itemData; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PrepareTPassmarkShape(const VLayoutPassmark &passmark, bool drawMode) -> QVector> +{ + QVector shape1; + if (passmark.lines.isEmpty()) + { + return {}; + } + + auto TurnPoint = [](QPointF point) + { + VLayoutPoint p(point); + p.SetTurnPoint(true); + return p; + }; + + QLineF line1 = passmark.lines.constFirst(); + shape1.append(TurnPoint(line1.p1())); + shape1.append(TurnPoint(line1.p2())); + + if (passmark.lines.size() <= 1) + { + return {shape1}; + } + + const QLineF &line2 = passmark.lines.constLast(); + + if (!drawMode) + { + shape1.append(TurnPoint(line2.p1())); + shape1.append(TurnPoint(line2.p2())); + shape1.append(TurnPoint(line1.p2())); + + return {shape1}; + } + + QVector shape2; + shape2.append(TurnPoint(line2.p1())); + shape2.append(TurnPoint(line2.p2())); + return {shape1, shape2}; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PrepareNoneBreakingPassmarkShape(const VLayoutPassmark &passmark) -> QVector> +{ + auto TurnPoint = [](QPointF point) + { + VLayoutPoint p(point); + p.SetTurnPoint(true); + return p; + }; + + QVector shape; + shape.reserve(passmark.lines.size() + 1); + for (int i = 0; i < passmark.lines.size(); ++i) + { + const QLineF &line = passmark.lines.at(i); + shape.append(TurnPoint(line.p1())); + + if (passmark.lines.size() - 1 == i) + { + shape.append(TurnPoint(line.p2())); + } + } + + return {shape}; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PrepareUPassmarkShape(const VLayoutPassmark &passmark) -> QVector> +{ + auto LayoutPoint = [](QPointF point, bool turnPoint, bool curvePoint) + { + VLayoutPoint p(point); + p.SetTurnPoint(turnPoint); + p.SetCurvePoint(curvePoint); + return p; + }; + + qreal radius = QLineF(passmark.baseLine.p1(), passmark.lines.constFirst().p1()).length(); + + if (passmark.baseLine.length() - radius > accuracyPointOnLine) + { + QVector lines = passmark.lines; + if (lines.size() < 3) + { + return {}; + } + + QLineF line1 = lines.takeFirst(); + + QVector shape; + shape.reserve(4 + passmark.lines.size() + 1); + + shape.append(LayoutPoint(line1.p1(), true, false)); + shape.append(LayoutPoint(line1.p2(), true, true)); + + QLineF line2 = lines.takeLast(); + + for (int i = 0; i < passmark.lines.size(); ++i) + { + const QLineF &line = passmark.lines.at(i); + shape.append(LayoutPoint(line.p1(), false, true)); + + if (passmark.lines.size() - 1 == i) + { + shape.append(LayoutPoint(line.p2(), false, true)); + } + } + + shape.append(LayoutPoint(line2.p1(), true, true)); + shape.append(LayoutPoint(line2.p2(), true, false)); + + return {shape}; + } + + QVector shape; + shape.reserve(passmark.lines.size() + 1); + for (int i = 0; i < passmark.lines.size(); ++i) + { + const QLineF &line = passmark.lines.at(i); + shape.append(LayoutPoint(line.p1(), false, true)); + + if (passmark.lines.size() - 1 == i) + { + shape.append(LayoutPoint(line.p2(), false, true)); + } + } + + if (!shape.isEmpty()) + { + shape.first().SetTurnPoint(true); + shape.last().SetTurnPoint(true); + } + + return {shape}; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto PreparePassmarkShape(const VLayoutPassmark &passmark, bool drawMode) -> QVector> +{ + switch (passmark.type) + { + case PassmarkLineType::OneLine: + case PassmarkLineType::InternalVMark: + case PassmarkLineType::ExternalVMark: + case PassmarkLineType::BoxMark: + case PassmarkLineType::CheckMark: + return PrepareNoneBreakingPassmarkShape(passmark); + break; + case PassmarkLineType::TMark: + return PrepareTPassmarkShape(passmark, drawMode); + break; + case PassmarkLineType::UMark: + return PrepareUPassmarkShape(passmark); + break; + default: + break; + } + + return {}; +} + +//--------------------------------------------------------------------------------------------------------------------- +void ConvertTwoLinesPassmark(const VLayoutPassmark &passmark, QList ¬chSequence) +{ + if (!passmark.lines.isEmpty()) + { + VLayoutPassmark line1 = passmark; + + line1.lines = {passmark.lines.constFirst()}; + line1.type = PassmarkLineType::OneLine; + line1.baseLine = passmark.lines.constFirst(); + + VBoundarySequenceItemData itemData; + itemData.item = QVariant::fromValue(line1); + itemData.type = VBoundarySequenceItem::Passmark; + + FillSequance(itemData, notchSequence); + } + + if (passmark.lines.size() > 1) + { + VLayoutPassmark line2 = passmark; + + line2.lines = {passmark.lines.constLast()}; + line2.type = PassmarkLineType::OneLine; + line2.baseLine = passmark.lines.constLast(); + + VBoundarySequenceItemData itemData; + itemData.item = QVariant::fromValue(line2); + itemData.type = VBoundarySequenceItem::Passmark; + + FillSequance(itemData, notchSequence); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void ConvertThreeLinesPassmark(const VLayoutPassmark &passmark, QList ¬chSequence) +{ + if (!passmark.lines.isEmpty()) + { + VLayoutPassmark line1 = passmark; + + line1.lines = {passmark.lines.constFirst()}; + line1.type = PassmarkLineType::OneLine; + line1.baseLine = passmark.lines.constFirst(); + + VBoundarySequenceItemData itemData; + itemData.item = QVariant::fromValue(line1); + itemData.type = VBoundarySequenceItem::Passmark; + + FillSequance(itemData, notchSequence); + } + + if (passmark.lines.size() > 1) + { + VLayoutPassmark line2 = passmark; + + line2.lines = {passmark.lines.at(1)}; + line2.type = PassmarkLineType::OneLine; + line2.baseLine = passmark.lines.at(1); + + VBoundarySequenceItemData itemData; + itemData.item = QVariant::fromValue(line2); + itemData.type = VBoundarySequenceItem::Passmark; + + FillSequance(itemData, notchSequence); + } + + if (passmark.lines.size() > 2) + { + VLayoutPassmark line3 = passmark; + + line3.lines = {passmark.lines.constLast()}; + line3.type = PassmarkLineType::OneLine; + line3.baseLine = passmark.lines.constLast(); + + VBoundarySequenceItemData itemData; + itemData.item = QVariant::fromValue(line3); + itemData.type = VBoundarySequenceItem::Passmark; + + FillSequance(itemData, notchSequence); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +auto SubdividePath(const QVector &boundary, const QPointF &p, QVector &sub1, + QVector &sub2) -> bool +{ + if (boundary.size() < 2) + { + return false; + } + + bool found = false; + sub1.clear(); + sub2.clear(); + + auto BreakPoint = [p]() + { + VLayoutPoint breakPoint(p); + breakPoint.SetTurnPoint(true); + return breakPoint; + }; + + for (qint32 i = 0; i < boundary.count() - 1; ++i) + { + if (found) + { + sub2.append(boundary.at(i)); + + if (i + 1 == boundary.count() - 1) + { + sub2.append(boundary.at(i + 1)); + } + continue; + } + + if (!VGObject::IsPointOnLineSegment(p, static_cast(boundary.at(i)), + static_cast(boundary.at(i + 1)))) + { + sub1.append(boundary.at(i)); + continue; + } + + if (not VFuzzyComparePoints(boundary.at(i), p)) + { + sub1.append(boundary.at(i)); + sub1.append(BreakPoint()); + } + else + { + if (not sub1.isEmpty()) + { + sub1.append(BreakPoint()); + } + } + + if (not VFuzzyComparePoints(boundary.at(i + 1), p)) + { + sub2.append(BreakPoint()); + + if (i + 1 == boundary.count() - 1) + { + sub2.append(boundary.at(i + 1)); + } + } + + found = true; + } + + if (not found) + { + sub1.clear(); + } + + return found; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto InsertDisconnect(QList &sequence, int i, const VBoundarySequenceItemData &item, + bool drawMode) -> bool +{ + auto passmark = item.item.value(); + bool inserted = false; + + const auto boundary = sequence.at(i).item.value().Points(); + + QVector sub1; + QVector sub2; + if (!SubdividePath(boundary, passmark.baseLine.p1(), sub1, sub2)) + { + return false; + } + + sequence.removeAt(i); + + if (not sub2.isEmpty()) + { + sequence.insert(i, PrepareSequenceItem(sub2, drawMode, VBoundarySequenceItem::Boundary)); + } + + QVector> shape = PreparePassmarkShape(passmark, drawMode); + for (auto &subShape : shape) + { + sequence.insert(i, PrepareSequenceItem(subShape, drawMode, VBoundarySequenceItem::PassmarkShape)); + } + + if (not sub1.isEmpty()) + { + sequence.insert(i, PrepareSequenceItem(sub1, drawMode, VBoundarySequenceItem::Boundary)); + } + + inserted = true; + + return inserted; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto InsertCutOut(QList &sequence, int i, const VBoundarySequenceItemData &item, + bool drawMode) -> bool +{ + auto passmark = item.item.value(); + + QVector> shape = PreparePassmarkShape(passmark, drawMode); + if (shape.isEmpty()) + { + return false; + } + + const QVector &subShape = shape.constFirst(); + if (subShape.size() < 2) + { + return false; + } + + const auto boundary = sequence.at(i).item.value().Points(); + + QVector startSub1; + QVector startSub2; + if (!SubdividePath(boundary, subShape.constFirst(), startSub1, startSub2)) + { + return false; + } + + QVector endSub1; + QVector endSub2; + if (!SubdividePath(boundary, subShape.constLast(), endSub1, endSub2)) + { + return false; + } + + sequence.removeAt(i); + + if (not endSub2.isEmpty()) + { + sequence.insert(i, PrepareSequenceItem(endSub2, drawMode, VBoundarySequenceItem::Boundary)); + } + + sequence.insert(i, PrepareSequenceItem(subShape, drawMode, VBoundarySequenceItem::PassmarkShape)); + + if (not startSub1.isEmpty()) + { + sequence.insert(i, PrepareSequenceItem(startSub1, drawMode, VBoundarySequenceItem::Boundary)); + } + + return true; +} +} // namespace + +//--------------------------------------------------------------------------------------------------------------------- +VBoundary::VBoundary(const QVector &boundary, bool seamAllowance, bool builtInSeamAllowance) + : m_boundary(boundary), + m_seamAllowance(seamAllowance), + m_builtInSeamAllowance(builtInSeamAllowance) +{ +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VBoundary::Combine(const QVector &passmarks, bool drawMode, bool layoutAllowance) const + -> QList +{ + QList notchSequence; + + for (const auto &passmark : passmarks) + { + if (SkipPassmark(passmark, drawMode, layoutAllowance)) + { + continue; + } + + if (passmark.type == PassmarkLineType::TwoLines) + { + ConvertTwoLinesPassmark(passmark, notchSequence); + continue; + } + + if (passmark.type == PassmarkLineType::ThreeLines) + { + ConvertThreeLinesPassmark(passmark, notchSequence); + continue; + } + + VBoundarySequenceItemData itemData; + itemData.item = QVariant::fromValue(passmark); + itemData.type = VBoundarySequenceItem::Passmark; + + FillSequance(itemData, notchSequence); + } + + QList sequence; + sequence.append(PrepareSequenceItem(m_boundary, drawMode, VBoundarySequenceItem::Boundary)); + + for (auto &item : notchSequence) + { + if (item.type == VBoundarySequenceItem::Passmark) + { + InsertPassmark(item, sequence, drawMode); + } + } + + return sequence; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VBoundary::SkipPassmark(const VLayoutPassmark &passmark, bool drawMode, bool layoutAllowance) const -> bool +{ + if (m_seamAllowance) + { + if ((m_builtInSeamAllowance && !passmark.isBuiltIn) || (!m_builtInSeamAllowance && passmark.isBuiltIn)) + { + return true; + } + } + else + { + if (!passmark.isBuiltIn) + { + return true; + } + } + + if (layoutAllowance && (passmark.type == PassmarkLineType::ExternalVMark || + passmark.type == PassmarkLineType::OneLine || passmark.type == PassmarkLineType::TwoLines || + passmark.type == PassmarkLineType::ThreeLines || passmark.type == PassmarkLineType::TMark)) + { + return true; + } + + if (!drawMode && passmark.type == PassmarkLineType::ExternalVMark) + { + return true; + } + + return false; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VBoundary::InsertPassmark(const VBoundarySequenceItemData &item, QList &sequence, + bool drawMode) const +{ + auto passmark = item.item.value(); + + bool inserted = false; + for (int i = 0; i < sequence.size(); ++i) + { + const VBoundarySequenceItemData &itemData = sequence.at(i); + if (itemData.type != VBoundarySequenceItem::Boundary) + { + continue; + } + + switch (passmark.type) + { + case PassmarkLineType::OneLine: + case PassmarkLineType::TMark: + case PassmarkLineType::ExternalVMark: + inserted = InsertDisconnect(sequence, i, item, drawMode); + break; + case PassmarkLineType::UMark: + case PassmarkLineType::InternalVMark: + case PassmarkLineType::BoxMark: + case PassmarkLineType::CheckMark: + inserted = InsertCutOut(sequence, i, item, drawMode); + break; + default: + break; + } + + if (inserted) + { + break; + } + } + + if (not inserted) + { + QString pieceName; + if (!m_pieceName.isEmpty()) + { + pieceName = tr("Piece '%1'.").arg(m_pieceName) + ' '_L1; + } + + QString errorMsg; + if (!passmark.label.isEmpty()) + { + errorMsg = pieceName + tr("Unable to insert notch for point '%1'.").arg(passmark.label); + } + else + { + errorMsg = pieceName + tr("Unable to insert notch."); + } + + VAbstractApplication::VApp()->IsPedantic() + ? throw VException(errorMsg) + : qWarning() << VAbstractApplication::warningMessageSignature + errorMsg; + } +} diff --git a/src/libs/vlayout/vboundary.h b/src/libs/vlayout/vboundary.h new file mode 100644 index 000000000..3d5cab5a6 --- /dev/null +++ b/src/libs/vlayout/vboundary.h @@ -0,0 +1,85 @@ +/************************************************************************ + ** + ** @file vboundary.h + ** @author Roman Telezhynskyi + ** @date 24 11, 2023 + ** + ** @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) 2023 Valentina project + ** All Rights Reserved. + ** + ** Valentina is free software: you can redistribute it and/or modify + ** it under the terms of the GNU General Public License as published by + ** the Free Software Foundation, either version 3 of the License, or + ** (at your option) any later version. + ** + ** Valentina is distributed in the hope that it will be useful, + ** but WITHOUT ANY WARRANTY; without even the implied warranty of + ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + ** GNU General Public License for more details. + ** + ** You should have received a copy of the GNU General Public License + ** along with Valentina. If not, see . + ** + *************************************************************************/ + +#ifndef VBOUNDARY_H +#define VBOUNDARY_H + +#include "../vgeometry/vgeometrydef.h" +#include "vlayoutpoint.h" + +#include +#include +#include +#include + +enum class VBoundarySequenceItem : char +{ + Boundary, + Passmark, + PassmarkShape, + Unknown +}; + +struct VBoundarySequenceItemData +{ + int number{0}; + VBoundarySequenceItem type{VBoundarySequenceItem::Unknown}; + QVariant item{}; +}; + +class VBoundary +{ + Q_DECLARE_TR_FUNCTIONS(VBoundary) // NOLINT + +public: + VBoundary(const QVector &boundary, bool seamAllowance, bool builtInSeamAllowance = false); + + auto Combine(const QVector &passmarks, bool drawMode, bool layoutAllowance = false) const + -> QList; + + void SetPieceName(const QString &newPieceName); + +private: + QVector m_boundary; + bool m_seamAllowance; + bool m_builtInSeamAllowance; + QString m_pieceName{}; + + auto SkipPassmark(const VLayoutPassmark &passmark, bool drawMode, bool layoutAllowance) const -> bool; + + void InsertPassmark(const VBoundarySequenceItemData &item, QList &sequence, + bool drawMode) const; +}; + +//--------------------------------------------------------------------------------------------------------------------- +inline void VBoundary::SetPieceName(const QString &newPieceName) +{ + m_pieceName = newPieceName; +} + +#endif // VBOUNDARY_H diff --git a/src/libs/vlayout/vlayout.pri b/src/libs/vlayout/vlayout.pri index 89ddbb039..faa416970 100644 --- a/src/libs/vlayout/vlayout.pri +++ b/src/libs/vlayout/vlayout.pri @@ -30,7 +30,8 @@ HEADERS += \ $$PWD/vlayoutpiecepath.h \ $$PWD/vlayoutpiecepath_p.h \ $$PWD/vbestsquare_p.h \ - $$PWD/vrawsapoint.h + $$PWD/vrawsapoint.h \ + $$PWD/vboundary.h SOURCES += \ $$PWD/vlayoutexporter.cpp \ @@ -50,6 +51,7 @@ SOURCES += \ $$PWD/vabstractpiece.cpp \ $$PWD/vlayoutpiece.cpp \ $$PWD/vlayoutpiecepath.cpp \ - $$PWD/vrawsapoint.cpp + $$PWD/vrawsapoint.cpp \ + $$PWD/vboundary.cpp *msvc*:SOURCES += $$PWD/stable.cpp diff --git a/src/libs/vlayout/vlayout.qbs b/src/libs/vlayout/vlayout.qbs index 556468847..902ab8ff1 100644 --- a/src/libs/vlayout/vlayout.qbs +++ b/src/libs/vlayout/vlayout.qbs @@ -55,7 +55,9 @@ VLib { "vabstractpiece.cpp", "vlayoutpiece.cpp", "vlayoutpiecepath.cpp", - "vrawsapoint.cpp" + "vrawsapoint.cpp", + "vboundary.h", + "vboundary.cpp" ]; if (Qt.core.versionMajor >= 5 && Qt.core.versionMinor < 12) { diff --git a/src/libs/vlayout/vlayoutexporter.cpp b/src/libs/vlayout/vlayoutexporter.cpp index 168e4f8d7..0cefb1455 100644 --- a/src/libs/vlayout/vlayoutexporter.cpp +++ b/src/libs/vlayout/vlayoutexporter.cpp @@ -324,6 +324,7 @@ void VLayoutExporter::ExportToAAMADXF(const QVector &details) cons generator.SetInsunits(VarInsunits::Millimeters); // Decided to always use mm. See issue #745 generator.SetXScale(m_xScale); generator.SetYScale(m_yScale); + generator.SetBoundaryTogetherWithNotches(m_togetherWithNotches); if (not generator.ExportToAAMA(details)) { qCritical() << tr("Can't create an AAMA dxf file.") << generator.ErrorString(); @@ -342,6 +343,7 @@ void VLayoutExporter::ExportToASTMDXF(const QVector &details) cons generator.SetInsunits(VarInsunits::Millimeters); // Decided to always use mm. See issue #745 generator.SetXScale(m_xScale); generator.SetYScale(m_yScale); + generator.SetBoundaryTogetherWithNotches(m_togetherWithNotches); if (not generator.ExportToASTM(details)) { qCritical() << tr("Can't create an ASTM dxf file.") << generator.ErrorString(); @@ -383,6 +385,7 @@ void VLayoutExporter::ExportToHPGL(const QVector &details) const generator.SetSingleLineFont(m_singleLineFont); generator.SetSingleStrokeOutlineFont(m_singleStrokeOutlineFont); generator.SetPenWidth(m_penWidth); + generator.SetBoundaryTogetherWithNotches(m_togetherWithNotches); if (not generator.ExportToHPGL(details)) { qCritical() << tr("Can't create an HP-GL file."); @@ -401,6 +404,7 @@ void VLayoutExporter::ExportToHPGL2(const QVector &details) const generator.SetSingleLineFont(m_singleLineFont); generator.SetSingleStrokeOutlineFont(m_singleStrokeOutlineFont); generator.SetPenWidth(m_penWidth); + generator.SetBoundaryTogetherWithNotches(m_togetherWithNotches); if (not generator.ExportToHPGL2(details)) { qCritical() << tr("Can't create an HP-GL file."); diff --git a/src/libs/vlayout/vlayoutexporter.h b/src/libs/vlayout/vlayoutexporter.h index 7e2db46e9..de1ba71d9 100644 --- a/src/libs/vlayout/vlayoutexporter.h +++ b/src/libs/vlayout/vlayoutexporter.h @@ -83,6 +83,9 @@ public: auto DxfVersion() const -> int; void SetDxfVersion(int dxfVersion); + void SetBoundaryTogetherWithNotches(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + void ExportToSVG(QGraphicsScene *scene, const QList &details) const; void ExportToPNG(QGraphicsScene *scene, const QList &details) const; void ExportToTIF(QGraphicsScene *scene, const QList &details) const; @@ -134,6 +137,7 @@ private: bool m_singleLineFont{false}; bool m_singleStrokeOutlineFont{false}; int m_penWidth{1}; + bool m_togetherWithNotches{false}; void ExportToPDF(QGraphicsScene *scene, const QList &details, const QString &filename) const; }; @@ -270,6 +274,18 @@ inline void VLayoutExporter::SetDxfVersion(int dxfVersion) m_dxfVersion = dxfVersion; } +//--------------------------------------------------------------------------------------------------------------------- +inline void VLayoutExporter::SetBoundaryTogetherWithNotches(bool value) +{ + m_togetherWithNotches = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VLayoutExporter::IsBoundaryTogetherWithNotches() const -> bool +{ + return m_togetherWithNotches; +} + //--------------------------------------------------------------------------------------------------------------------- inline auto VLayoutExporter::offset() const -> QPointF { diff --git a/src/libs/vlayout/vlayoutgenerator.cpp b/src/libs/vlayout/vlayoutgenerator.cpp index 0b3d0b467..e89480907 100644 --- a/src/libs/vlayout/vlayoutgenerator.cpp +++ b/src/libs/vlayout/vlayoutgenerator.cpp @@ -42,32 +42,7 @@ //--------------------------------------------------------------------------------------------------------------------- VLayoutGenerator::VLayoutGenerator(QObject *parent) - : QObject(parent), - papers(), - bank(new VBank()), - paperHeight(0), - paperWidth(0), - margins(), - usePrinterFields(true), -#ifdef Q_CC_MSVC - // See https://stackoverflow.com/questions/15750917/initializing-stdatomic-bool - stopGeneration(ATOMIC_VAR_INIT(false)), -#else - stopGeneration(false), -#endif - state(LayoutErrors::NoError), - shift(0), - rotate(true), - followGrainline(false), - rotationNumber(2), - autoCropLength(false), - autoCropWidth(false), - saveLength(false), - unitePages(false), - stripOptimizationEnabled(false), - multiplier(1), - stripOptimization(false), - textAsPaths(false) + : QObject(parent) { } @@ -134,7 +109,7 @@ void VLayoutGenerator::Generate(const QElapsedTimer &timer, qint64 timeout, Layo if (VFuzzyComparePossibleNulls(shift, -1)) { - if (bank->PrepareDetails()) + if (bank->PrepareDetails(togetherWithNotches)) { SetShift(ToPixel(1, Unit::Cm)); } @@ -308,7 +283,8 @@ auto VLayoutGenerator::GetPapersItems() const -> QList list.reserve(papers.count()); for (const auto &paper : papers) { - list.append(paper.GetPaperItem(autoCropLength, autoCropWidth, IsTestAsPaths())); + list.append( + paper.GetPaperItem(autoCropLength, autoCropWidth, textAsPaths, togetherWithNotches, showLayoutAllowance)); } return list; } @@ -332,7 +308,7 @@ auto VLayoutGenerator::GetAllDetailsItems() const -> QList bool +{ + return togetherWithNotches; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutGenerator::SetBoundaryTogetherWithNotches(bool value) +{ + togetherWithNotches = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VLayoutGenerator::IsShowLayoutAllowance() const -> bool +{ + return showLayoutAllowance; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutGenerator::SetShowLayoutAllowance(bool value) +{ + showLayoutAllowance = value; +} + //--------------------------------------------------------------------------------------------------------------------- auto VLayoutGenerator::IsRotationNeeded() const -> bool { @@ -397,10 +397,8 @@ auto VLayoutGenerator::IsRotationNeeded() const -> bool { return bank->IsRotationNeeded(); } - else - { - return true; - } + + return true; } //--------------------------------------------------------------------------------------------------------------------- diff --git a/src/libs/vlayout/vlayoutgenerator.h b/src/libs/vlayout/vlayoutgenerator.h index 3fbfaa936..4d5d62b20 100644 --- a/src/libs/vlayout/vlayoutgenerator.h +++ b/src/libs/vlayout/vlayoutgenerator.h @@ -29,30 +29,30 @@ #ifndef VLAYOUTGENERATOR_H #define VLAYOUTGENERATOR_H - #include +#include #include #include #include #include #include -#include #include -#include +#include #include "vbank.h" #include "vlayoutdef.h" +#include "vlayoutpaper.h" class QGraphicsItem; -class VLayoutPaper; class QElapsedTimer; -class VLayoutGenerator :public QObject +class VLayoutGenerator : public QObject { Q_OBJECT // NOLINT + public: explicit VLayoutGenerator(QObject *parent = nullptr); - virtual ~VLayoutGenerator() override; + ~VLayoutGenerator() override; void SetDetails(const QVector &details); void SetLayoutWidth(qreal width); @@ -70,14 +70,14 @@ public: void SetNestingTime(int value); auto GetEfficiencyCoefficient() const -> qreal; - void SetEfficiencyCoefficient(qreal coefficient); + void SetEfficiencyCoefficient(qreal coefficient); auto IsUsePrinterFields() const -> bool; auto GetPrinterFields() const -> QMarginsF; void SetPrinterFields(bool usePrinterFields, const QMarginsF &value); auto GetShift() const -> qreal; - void SetShift(qreal shift); + void SetShift(qreal shift); void Generate(const QElapsedTimer &timer, qint64 timeout, LayoutErrors previousState = LayoutErrors::NoError); @@ -124,7 +124,7 @@ public: void SetUnitePages(bool value); auto GetMultiplier() const -> quint8; - void SetMultiplier(quint8 value); + void SetMultiplier(quint8 value); auto IsStripOptimization() const -> bool; void SetStripOptimization(bool value); @@ -132,6 +132,12 @@ public: auto IsTestAsPaths() const -> bool; void SetTextAsPaths(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + void SetBoundaryTogetherWithNotches(bool value); + + auto IsShowLayoutAllowance() const -> bool; + void SetShowLayoutAllowance(bool value); + auto IsRotationNeeded() const -> bool; auto IsPortrait() const -> bool; @@ -142,29 +148,37 @@ public slots: private: Q_DISABLE_COPY_MOVE(VLayoutGenerator) // NOLINT - QVector papers; - VBank *bank; - qreal paperHeight; - qreal paperWidth; - QMarginsF margins; - bool usePrinterFields; - std::atomic_bool stopGeneration; - LayoutErrors state; - qreal shift; - bool rotate; - bool followGrainline; - int rotationNumber; - bool autoCropLength; - bool autoCropWidth; - bool saveLength; + QVector papers{}; + VBank *bank{new VBank()}; + qreal paperHeight{0}; + qreal paperWidth{0}; + QMarginsF margins{}; + bool usePrinterFields{true}; + std::atomic_bool stopGeneration{ +#ifdef Q_CC_MSVC + ATOMIC_VAR_INIT(false) +#else + false +#endif + }; + LayoutErrors state{LayoutErrors::NoError}; + qreal shift{0}; + bool rotate{true}; + bool followGrainline{false}; + int rotationNumber{2}; + bool autoCropLength{false}; + bool autoCropWidth{false}; + bool saveLength{false}; bool preferOneSheetSolution{false}; - bool unitePages; - bool stripOptimizationEnabled; - quint8 multiplier; - bool stripOptimization; - bool textAsPaths; + bool unitePages{false}; + bool stripOptimizationEnabled{false}; + quint8 multiplier{1}; + bool stripOptimization{false}; + bool textAsPaths{false}; + bool togetherWithNotches{false}; int nestingTime{1}; qreal efficiencyCoefficient{0.0}; + bool showLayoutAllowance{false}; auto PageHeight() const -> int; auto PageWidth() const -> int; @@ -172,7 +186,7 @@ private: void OptimizeWidth(); void GatherPages(); void UnitePages(); - void UniteDetails(int j, QList > &nDetails, qreal length, int i) const; + void UniteDetails(int j, QList> &nDetails, qreal length, int i) const; void UnitePapers(int j, QList &papersLength, qreal length); auto MoveDetails(qreal length, const QVector &details) const -> QList; auto MasterPage() const -> VLayoutPaper; diff --git a/src/libs/vlayout/vlayoutpaper.cpp b/src/libs/vlayout/vlayoutpaper.cpp index da6d10851..785f5752d 100644 --- a/src/libs/vlayout/vlayoutpaper.cpp +++ b/src/libs/vlayout/vlayoutpaper.cpp @@ -321,7 +321,8 @@ auto VLayoutPaper::SaveResult(const VBestSquare &bestResult, const VLayoutPiece } //--------------------------------------------------------------------------------------------------------------------- -auto VLayoutPaper::GetPaperItem(bool autoCropLength, bool autoCropWidth, bool textAsPaths) const -> QGraphicsRectItem * +auto VLayoutPaper::GetPaperItem(bool autoCropLength, bool autoCropWidth, bool textAsPaths, bool togetherWithNotches, + bool showLayoutAllowance) const -> QGraphicsRectItem * { int height = d->globalContour.GetHeight(); int width = d->globalContour.GetWidth(); @@ -329,7 +330,7 @@ auto VLayoutPaper::GetPaperItem(bool autoCropLength, bool autoCropWidth, bool te if (autoCropLength || autoCropWidth) { QScopedPointer scene(new QGraphicsScene()); - QList list = GetItemDetails(textAsPaths); + QList list = GetItemDetails(textAsPaths, togetherWithNotches, showLayoutAllowance); for (auto *item : list) { scene->addItem(item); @@ -417,13 +418,14 @@ auto VLayoutPaper::GetGlobalContour() const -> QGraphicsPathItem * } //--------------------------------------------------------------------------------------------------------------------- -auto VLayoutPaper::GetItemDetails(bool textAsPaths) const -> QList +auto VLayoutPaper::GetItemDetails(bool textAsPaths, bool togetherWithNotches, bool showLayoutAllowance) const + -> QList { QList list; list.reserve(d->details.count()); for (const auto &detail : d->details) { - list.append(detail.GetItem(textAsPaths)); + list.append(detail.GetItem(textAsPaths, togetherWithNotches, showLayoutAllowance)); } return list; } diff --git a/src/libs/vlayout/vlayoutpaper.h b/src/libs/vlayout/vlayoutpaper.h index 5a8c5b89a..2a1491b0f 100644 --- a/src/libs/vlayout/vlayoutpaper.h +++ b/src/libs/vlayout/vlayoutpaper.h @@ -92,10 +92,12 @@ public: auto ArrangeDetail(const VLayoutPiece &detail, std::atomic_bool &stop) -> bool; auto Count() const -> vsizetype; - Q_REQUIRED_RESULT auto GetPaperItem(bool autoCropLength, bool autoCropWidth, bool textAsPaths) const + Q_REQUIRED_RESULT auto GetPaperItem(bool autoCropLength, bool autoCropWidth, bool textAsPaths, + bool togetherWithNotches, bool showLayoutAllowance) const -> QGraphicsRectItem *; Q_REQUIRED_RESULT auto GetGlobalContour() const -> QGraphicsPathItem *; - Q_REQUIRED_RESULT auto GetItemDetails(bool textAsPaths) const -> QList; + Q_REQUIRED_RESULT auto GetItemDetails(bool textAsPaths, bool togetherWithNotches, bool showLayoutAllowance) const + -> QList; auto GetDetails() const -> QVector; void SetDetails(const QVector &details); diff --git a/src/libs/vlayout/vlayoutpiece.cpp b/src/libs/vlayout/vlayoutpiece.cpp index 0246fa310..f3e4da4f6 100644 --- a/src/libs/vlayout/vlayoutpiece.cpp +++ b/src/libs/vlayout/vlayoutpiece.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +52,7 @@ #include "../vgeometry/vlayoutplacelabel.h" #include "../vgeometry/vplacelabelitem.h" #include "../vgeometry/vpointf.h" +#include "../vlayout/vabstractpiece.h" #include "../vmisc/compatibility.h" #include "../vmisc/literals.h" #include "../vmisc/svgfont/vsvgfontdatabase.h" @@ -65,6 +67,7 @@ #include "../vpatterndb/vpassmark.h" #include "../vpatterndb/vpiecenode.h" #include "../vwidgets/vpiecegrainline.h" +#include "vboundary.h" #include "vgraphicsfillitem.h" #include "vlayoutpiece_p.h" #include "vtextmanager.h" @@ -241,14 +244,6 @@ auto ConvertPlaceLabels(const VPiece &piece, const VContainer *pattern) -> QVect auto PrepareSAPassmark(const VPiece &piece, const VContainer *pattern, const VPassmark &passmark, PassmarkSide side, bool &ok) -> VLayoutPassmark { - QT_WARNING_PUSH - QT_WARNING_DISABLE_GCC("-Wnoexcept") - // noexcept-expression evaluates to 'false' because of a call to 'constexpr QPointF::QPointF()' - - VLayoutPassmark layoutPassmark; - - QT_WARNING_POP - VPiecePassmarkData pData = passmark.Data(); const QVector path = piece.GetUnitedPath(pattern); const int nodeIndex = VPiecePath::indexOfNode(path, pData.id); @@ -276,7 +271,15 @@ auto PrepareSAPassmark(const VPiece &piece, const VContainer *pattern, const VPa return {}; } - if (side == PassmarkSide::All || side == PassmarkSide::Right) + QT_WARNING_PUSH + QT_WARNING_DISABLE_GCC("-Wnoexcept") + // noexcept-expression evaluates to 'false' because of a call to 'constexpr QPointF::QPointF()' + + VLayoutPassmark layoutPassmark; + + QT_WARNING_POP + + if (side == PassmarkSide::All || side == PassmarkSide::Left) { layoutPassmark.baseLine = baseLines.constFirst(); } @@ -301,6 +304,7 @@ auto PrepareSAPassmark(const VPiece &piece, const VContainer *pattern, const VPa layoutPassmark.type = pData.passmarkLineType; layoutPassmark.isBuiltIn = false; layoutPassmark.isClockwiseOpening = pData.passmarkSAPoint.IsPassmarkClockwiseOpening(); + layoutPassmark.label = pData.nodeName; ok = true; return layoutPassmark; @@ -364,92 +368,12 @@ auto PreapreBuiltInSAPassmark(const VPiece &piece, const VContainer *pattern, co layoutPassmark.type = pData.passmarkLineType; layoutPassmark.isBuiltIn = true; layoutPassmark.isClockwiseOpening = pData.passmarkSAPoint.IsPassmarkClockwiseOpening(); + layoutPassmark.label = pData.nodeName; ok = true; return layoutPassmark; } -//--------------------------------------------------------------------------------------------------------------------- -auto ConvertPassmarks(const VPiece &piece, const VContainer *pattern) -> QVector -{ - const QVector passmarks = piece.Passmarks(pattern); - QVector layoutPassmarks; - layoutPassmarks.reserve(passmarks.size()); - - for (const auto &passmark : passmarks) - { - if (passmark.IsNull()) - { - continue; - } - - auto AddPassmark = [passmark, piece, pattern, &layoutPassmarks](PassmarkSide side) - { - bool ok = false; - VLayoutPassmark layoutPassmark = PrepareSAPassmark(piece, pattern, passmark, side, ok); - if (ok) - { - layoutPassmarks.append(layoutPassmark); - } - }; - - auto AddBuiltInPassmark = [passmark, piece, pattern, &layoutPassmarks]() - { - bool ok = false; - VLayoutPassmark layoutPassmark = PreapreBuiltInSAPassmark(piece, pattern, passmark, ok); - if (ok) - { - layoutPassmarks.append(layoutPassmark); - } - }; - - if (piece.IsSeamAllowanceBuiltIn()) - { - AddBuiltInPassmark(); - continue; - } - - VPiecePassmarkData pData = passmark.Data(); - - switch (pData.passmarkAngleType) - { - case PassmarkAngleType::Straightforward: - case PassmarkAngleType::Bisector: - AddPassmark(PassmarkSide::All); - break; - case PassmarkAngleType::Intersection: - case PassmarkAngleType::Intersection2: - AddPassmark(PassmarkSide::Left); - AddPassmark(PassmarkSide::Right); - break; - case PassmarkAngleType::IntersectionOnlyLeft: - case PassmarkAngleType::Intersection2OnlyLeft: - AddPassmark(PassmarkSide::Left); - break; - case PassmarkAngleType::IntersectionOnlyRight: - case PassmarkAngleType::Intersection2OnlyRight: - AddPassmark(PassmarkSide::Right); - break; - default: - break; - } - - if (VAbstractApplication::VApp()->Settings()->IsDoublePassmark() && - (VAbstractApplication::VApp()->Settings()->IsPieceShowMainPath() || not piece.IsHideMainPath()) && - pData.isMainPathNode && pData.passmarkAngleType != PassmarkAngleType::Intersection && - pData.passmarkAngleType != PassmarkAngleType::IntersectionOnlyLeft && - pData.passmarkAngleType != PassmarkAngleType::IntersectionOnlyRight && - pData.passmarkAngleType != PassmarkAngleType::Intersection2 && - pData.passmarkAngleType != PassmarkAngleType::Intersection2OnlyLeft && - pData.passmarkAngleType != PassmarkAngleType::Intersection2OnlyRight && pData.isShowSecondPassmark) - { - AddBuiltInPassmark(); - } - } - - return layoutPassmarks; -} - //--------------------------------------------------------------------------------------------------------------------- auto PrepareGradationPlaceholders(const VContainer *data) -> QMap { @@ -640,7 +564,8 @@ auto VLayoutPiece::Create(const VPiece &piece, vidtype id, const VContainer *pat QFuture> futureMainPath = QtConcurrent::run([piece, pattern]() { return piece.MainPathPoints(pattern); }); QFuture> futureInternalPaths = QtConcurrent::run(ConvertInternalPaths, piece, pattern); - QFuture> futurePassmarks = QtConcurrent::run(ConvertPassmarks, piece, pattern); + QFuture> futurePassmarks = + QtConcurrent::run(VLayoutPiece::ConvertPassmarks, piece, pattern); QFuture> futurePlaceLabels = QtConcurrent::run(ConvertPlaceLabels, piece, pattern); VLayoutPiece det; @@ -676,7 +601,7 @@ auto VLayoutPiece::Create(const VPiece &piece, vidtype id, const VContainer *pat det.SetPriority(piece.GetPriority()); // Very important to set main path first! - if (det.MappedContourPath().isEmpty()) + if (det.MappedContourPath(false, false).isEmpty()) { throw VException(tr("Piece %1 doesn't have shape.").arg(piece.GetName())); } @@ -1233,7 +1158,7 @@ auto VLayoutPiece::isNull() const -> bool { if (not d->m_contour.isEmpty() && d->m_layoutWidth > 0) { - return not(IsSeamAllowance() && not IsSeamAllowanceBuiltIn() && not d->m_seamAllowance.isEmpty()); + return !IsSeamAllowance() || IsSeamAllowanceBuiltIn() || d->m_seamAllowance.isEmpty(); } return true; } @@ -1245,40 +1170,46 @@ auto VLayoutPiece::Square() const -> qint64 } //--------------------------------------------------------------------------------------------------------------------- -void VLayoutPiece::SetLayoutAllowancePoints() +void VLayoutPiece::SetLayoutAllowancePoints(bool togetherWithNotches) { d->m_square = 0; if (d->m_layoutWidth > 0) { - if (IsSeamAllowance() && not IsSeamAllowanceBuiltIn()) - { - QVector seamAllowancePoints; - CastTo(GetMappedSeamAllowancePoints(), seamAllowancePoints); - CastTo(Equidistant(seamAllowancePoints, d->m_layoutWidth, GetName()), d->m_layoutAllowance); - if (not d->m_layoutAllowance.isEmpty()) - { - d->m_layoutAllowance.removeLast(); + QVector pieceBoundary = IsSeamAllowance() && not IsSeamAllowanceBuiltIn() + ? GetMappedSeamAllowancePoints() + : GetMappedContourPoints(); - QVector points; - CastTo(GetSeamAllowancePoints(), points); - d->m_square = qFloor(qAbs(SumTrapezoids(points) / 2.0)); + if (togetherWithNotches) + { + const QVector passmarks = GetMappedPassmarks(); + bool seamAllowance = IsSeamAllowance() && !IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = IsSeamAllowance() && IsSeamAllowanceBuiltIn(); + + VBoundary boundary(pieceBoundary, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(GetName()); + const QList sequence = boundary.Combine(passmarks, false, true); + + pieceBoundary.clear(); + + for (const auto &item : sequence) + { + pieceBoundary += item.item.value().Points(); } } - else - { - QVector seamLinePoints; - CastTo(GetMappedContourPoints(), seamLinePoints); - CastTo(Equidistant(seamLinePoints, d->m_layoutWidth, GetName()), d->m_layoutAllowance); - if (not d->m_layoutAllowance.isEmpty()) - { - d->m_layoutAllowance.removeLast(); - QVector points; - CastTo(GetContourPoints(), points); - d->m_square = qFloor(qAbs(SumTrapezoids(points) / 2.0)); - } + QVector pieceBoundaryPoints; + CastTo(pieceBoundary, pieceBoundaryPoints); + CastTo(Equidistant(pieceBoundaryPoints, d->m_layoutWidth, GetName()), d->m_layoutAllowance); + if (not d->m_layoutAllowance.isEmpty()) + { + d->m_layoutAllowance.removeLast(); } + + QVector points; + CastTo(IsSeamAllowance() && not IsSeamAllowanceBuiltIn() ? GetSeamAllowancePoints() : GetContourPoints(), + points); + d->m_square = qFloor(qAbs(SumTrapezoids(points) / 2.0)); } else { @@ -1362,20 +1293,40 @@ void VLayoutPiece::SetInternalPaths(const QVector &internalPat } //--------------------------------------------------------------------------------------------------------------------- -auto VLayoutPiece::MappedContourPath() const -> QPainterPath +auto VLayoutPiece::MappedContourPath(bool togetherWithNotches, bool showLayoutAllowance) const -> QPainterPath { - return d->m_matrix.map(ContourPath()); + return d->m_matrix.map(ContourPath(togetherWithNotches, showLayoutAllowance)); } //--------------------------------------------------------------------------------------------------------------------- -auto VLayoutPiece::ContourPath() const -> QPainterPath +auto VLayoutPiece::ContourPath(bool togetherWithNotches, bool showLayoutAllowance) const -> QPainterPath { QPainterPath path; - // contour + // sew line if (not IsHideMainPath() || not IsSeamAllowance() || IsSeamAllowanceBuiltIn()) { - path = VGObject::PainterPath(GetContourPoints()); + if (togetherWithNotches) + { + bool seamAllowance = IsSeamAllowance() && IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = IsSeamAllowance() && IsSeamAllowanceBuiltIn(); + + VBoundary boundary(d->m_contour, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(GetName()); + const QList sequence = boundary.Combine(d->m_passmarks, true, false); + + for (const auto &item : sequence) + { + const auto itemPath = item.item.value().Points(); + QVector convertedPoints; + CastTo(itemPath, convertedPoints); + path.addPolygon(QPolygonF(convertedPoints)); + } + } + else + { + path = VGObject::PainterPath(GetContourPoints()); + } } // seam allowance @@ -1384,39 +1335,55 @@ auto VLayoutPiece::ContourPath() const -> QPainterPath if (not IsSeamAllowanceBuiltIn()) { // Draw seam allowance - QVector points = GetSeamAllowancePoints(); - - if (points.constLast().toPoint() != points.constFirst().toPoint()) + if (togetherWithNotches) { - points.append(points.at(0)); // Should be always closed - } + VBoundary boundary(d->m_seamAllowance, true); + boundary.SetPieceName(GetName()); + const QList sequence = boundary.Combine(d->m_passmarks, true, false); - QPainterPath ekv; - ekv.moveTo(points.at(0)); - for (qint32 i = 1; i < points.count(); ++i) + for (const auto &item : sequence) + { + const auto itemPath = item.item.value().Points(); + QVector convertedPoints; + CastTo(itemPath, convertedPoints); + path.addPolygon(QPolygonF(convertedPoints)); + } + } + else { - ekv.lineTo(points.at(i)); - } + QVector points = d->m_seamAllowance; + if (points.constLast().toPoint() != points.constFirst().toPoint()) + { + points.append(points.at(0)); // Should be always closed + } - path.addPath(ekv); + path.addPath(VGObject::PainterPath(points)); + } } - // Draw passmarks - QPainterPath passmaksPath; - const QVector passmarks = GetPassmarks(); - for (const auto &passmark : passmarks) + if (!togetherWithNotches) { - for (const auto &line : passmark.lines) + // Draw passmarks + QPainterPath passmaksPath; + for (const auto &passmark : d->m_passmarks) { - passmaksPath.moveTo(line.p1()); - passmaksPath.lineTo(line.p2()); + for (const auto &line : passmark.lines) + { + passmaksPath.moveTo(line.p1()); + passmaksPath.lineTo(line.p2()); + } } + path.addPath(passmaksPath); } - path.addPath(passmaksPath); path.setFillRule(Qt::WindingFill); } + if (showLayoutAllowance) + { + path.addPath(VGObject::PainterPath(d->m_layoutAllowance)); + } + return path; } @@ -1427,9 +1394,9 @@ auto VLayoutPiece::MappedLayoutAllowancePath() const -> QPainterPath } //--------------------------------------------------------------------------------------------------------------------- -void VLayoutPiece::DrawMiniature(QPainter &painter) const +void VLayoutPiece::DrawMiniature(QPainter &painter, bool togetherWithNotches) const { - painter.drawPath(ContourPath()); + painter.drawPath(ContourPath(togetherWithNotches, false)); for (const auto &path : d->m_internalPaths) { @@ -1453,9 +1420,10 @@ void VLayoutPiece::DrawMiniature(QPainter &painter) const } //--------------------------------------------------------------------------------------------------------------------- -auto VLayoutPiece::GetItem(bool textAsPaths) const -> QGraphicsItem * +auto VLayoutPiece::GetItem(bool textAsPaths, bool togetherWithNotches, bool showLayoutAllowance) const + -> QGraphicsItem * { - QGraphicsPathItem *item = GetMainItem(); + QGraphicsPathItem *item = GetMainItem(togetherWithNotches, showLayoutAllowance); for (const auto &path : d->m_internalPaths) { @@ -1485,10 +1453,31 @@ auto VLayoutPiece::GetItem(bool textAsPaths) const -> QGraphicsItem * } //--------------------------------------------------------------------------------------------------------------------- -auto VLayoutPiece::IsLayoutAllowanceValid() const -> bool +auto VLayoutPiece::IsLayoutAllowanceValid(bool togetherWithNotches) const -> bool { QVector base = (IsSeamAllowance() && not IsSeamAllowanceBuiltIn()) ? d->m_seamAllowance : d->m_contour; + + if (togetherWithNotches) + { + const QVector passmarks = GetMappedPassmarks(); + bool seamAllowance = IsSeamAllowance() && !IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = IsSeamAllowance() && IsSeamAllowanceBuiltIn(); + + VBoundary boundary(base, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(GetName()); + const QList sequence = boundary.Combine(passmarks, false, true); + + base.clear(); + + for (const auto &item : sequence) + { + base += item.item.value().Points(); + } + + base = VAbstractPiece::RemoveDublicates(base, false); + } + QVector points; CastTo(base, points); return VAbstractPiece::IsAllowanceValid(points, d->m_layoutAllowance); @@ -1820,13 +1809,13 @@ auto VLayoutPiece::DetailPath() const -> QVector } //--------------------------------------------------------------------------------------------------------------------- -auto VLayoutPiece::GetMainItem() const -> QGraphicsPathItem * +auto VLayoutPiece::GetMainItem(bool togetherWithNotches, bool showLayoutAllowance) const -> QGraphicsPathItem * { auto *item = new QGraphicsPathItem(); QPen pen = item->pen(); pen.setWidthF(VAbstractApplication::VApp()->Settings()->WidthHairLine()); item->setPen(pen); - item->setPath(MappedContourPath()); + item->setPath(MappedContourPath(togetherWithNotches, showLayoutAllowance)); return item; } @@ -1953,3 +1942,84 @@ template auto VLayoutPiece::Map(QVector points) const -> QVector { return MapVector(points, d->m_matrix, d->m_mirror); } + +//--------------------------------------------------------------------------------------------------------------------- +auto VLayoutPiece::ConvertPassmarks(const VPiece &piece, const VContainer *pattern) -> QVector +{ + const QVector passmarks = piece.Passmarks(pattern); + QVector layoutPassmarks; + layoutPassmarks.reserve(passmarks.size()); + + for (const auto &passmark : passmarks) + { + if (passmark.IsNull()) + { + continue; + } + + auto AddPassmark = [passmark, piece, pattern, &layoutPassmarks](PassmarkSide side) + { + bool ok = false; + VLayoutPassmark layoutPassmark = PrepareSAPassmark(piece, pattern, passmark, side, ok); + if (ok) + { + layoutPassmarks.append(layoutPassmark); + } + }; + + auto AddBuiltInPassmark = [passmark, piece, pattern, &layoutPassmarks]() + { + bool ok = false; + VLayoutPassmark layoutPassmark = PreapreBuiltInSAPassmark(piece, pattern, passmark, ok); + if (ok) + { + layoutPassmarks.append(layoutPassmark); + } + }; + + if (piece.IsSeamAllowanceBuiltIn()) + { + AddBuiltInPassmark(); + continue; + } + + VPiecePassmarkData pData = passmark.Data(); + + switch (pData.passmarkAngleType) + { + case PassmarkAngleType::Straightforward: + case PassmarkAngleType::Bisector: + AddPassmark(PassmarkSide::All); + break; + case PassmarkAngleType::Intersection: + case PassmarkAngleType::Intersection2: + AddPassmark(PassmarkSide::Left); + AddPassmark(PassmarkSide::Right); + break; + case PassmarkAngleType::IntersectionOnlyLeft: + case PassmarkAngleType::Intersection2OnlyLeft: + AddPassmark(PassmarkSide::Left); + break; + case PassmarkAngleType::IntersectionOnlyRight: + case PassmarkAngleType::Intersection2OnlyRight: + AddPassmark(PassmarkSide::Right); + break; + default: + break; + } + + if (VAbstractApplication::VApp()->Settings()->IsDoublePassmark() && + (VAbstractApplication::VApp()->Settings()->IsPieceShowMainPath() || not piece.IsHideMainPath()) && + pData.isMainPathNode && pData.passmarkAngleType != PassmarkAngleType::Intersection && + pData.passmarkAngleType != PassmarkAngleType::IntersectionOnlyLeft && + pData.passmarkAngleType != PassmarkAngleType::IntersectionOnlyRight && + pData.passmarkAngleType != PassmarkAngleType::Intersection2 && + pData.passmarkAngleType != PassmarkAngleType::Intersection2OnlyLeft && + pData.passmarkAngleType != PassmarkAngleType::Intersection2OnlyRight && pData.isShowSecondPassmark) + { + AddBuiltInPassmark(); + } + } + + return layoutPassmarks; +} diff --git a/src/libs/vlayout/vlayoutpiece.h b/src/libs/vlayout/vlayoutpiece.h index 463eb41cc..6494dbaef 100644 --- a/src/libs/vlayout/vlayoutpiece.h +++ b/src/libs/vlayout/vlayoutpiece.h @@ -95,6 +95,7 @@ public: #endif static auto Create(const VPiece &piece, vidtype id, const VContainer *pattern) -> VLayoutPiece; + static auto ConvertPassmarks(const VPiece &piece, const VContainer *pattern) -> QVector; auto GetUniqueID() const -> QString override; @@ -109,7 +110,7 @@ public: auto GetMappedLayoutAllowancePoints() const -> QVector; auto GetLayoutAllowancePoints() const -> QVector; - void SetLayoutAllowancePoints(); + void SetLayoutAllowancePoints(bool togetherWithNotches); auto GetMappedExternalContourPoints() const -> QVector; auto GetExternalContourPoints() const -> QVector; @@ -204,15 +205,16 @@ public: auto isNull() const -> bool; auto Square() const -> qint64; - auto MappedContourPath() const -> QPainterPath; - auto ContourPath() const -> QPainterPath; + auto MappedContourPath(bool togetherWithNotches, bool showLayoutAllowance) const -> QPainterPath; + auto ContourPath(bool togetherWithNotches, bool showLayoutAllowance) const -> QPainterPath; auto MappedLayoutAllowancePath() const -> QPainterPath; - void DrawMiniature(QPainter &painter) const; + void DrawMiniature(QPainter &painter, bool togetherWithNotches) const; - Q_REQUIRED_RESULT auto GetItem(bool textAsPaths) const -> QGraphicsItem *; + Q_REQUIRED_RESULT auto GetItem(bool textAsPaths, bool togetherWithNotches, bool showLayoutAllowance) const + -> QGraphicsItem *; - auto IsLayoutAllowanceValid() const -> bool; + auto IsLayoutAllowanceValid(bool togetherWithNotches) const -> bool; auto BiggestEdge() const -> qreal; @@ -238,7 +240,7 @@ private: auto DetailPath() const -> QVector; - Q_REQUIRED_RESULT auto GetMainItem() const -> QGraphicsPathItem *; + Q_REQUIRED_RESULT auto GetMainItem(bool togetherWithNotches, bool showLayoutAllowance) const -> QGraphicsPathItem *; Q_REQUIRED_RESULT auto GetMainPathItem() const -> QGraphicsPathItem *; void LabelStringsSVGFont(QGraphicsItem *parent, const QVector &labelShape, const VTextManager &tm, diff --git a/src/libs/vlayout/vprintlayout.h b/src/libs/vlayout/vprintlayout.h index ab4c66cbb..db86466b4 100644 --- a/src/libs/vlayout/vprintlayout.h +++ b/src/libs/vlayout/vprintlayout.h @@ -34,7 +34,12 @@ #include "../vmisc/def.h" -enum class PrintType : qint8 {PrintPDF, PrintPreview, PrintNative}; +enum class PrintType : qint8 +{ + PrintPDF, + PrintPreview, + PrintNative +}; class QPrinter; class QGraphicsScene; @@ -43,9 +48,10 @@ struct VWatermarkData; class VPrintLayout : public QObject { Q_OBJECT // NOLINT + public: explicit VPrintLayout(QObject *parent = nullptr); - virtual ~VPrintLayout(); + ~VPrintLayout() override; auto FileName() const -> QString; void SetFileName(const QString &fileName); @@ -107,8 +113,11 @@ public: auto LayoutShadows() const -> QList; void SetLayoutShadows(const QList &layoutShadows); - auto LayoutDetails() const -> QList >; - void SetLayoutDetails(const QList > &layoutDetails); + auto LayoutDetails() const -> QList>; + void SetLayoutDetails(const QList> &layoutDetails); + + void SetBoundaryTogetherWithNotches(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; void PrintTiled(); void PrintOrigin(); @@ -125,34 +134,34 @@ public: static auto PrinterScaleDiff(QPrinter *printer) -> QPair; private slots: - void PrintPages (QPrinter *printer); + void PrintPages(QPrinter *printer); private: Q_DISABLE_COPY_MOVE(VPrintLayout) // NOLINT - QString m_fileName{}; - QSizeF m_layoutPaperSize{}; - QMarginsF m_layoutMargins{}; - QWidget *m_parentWidget{nullptr}; - bool m_isLayoutPortrait{true}; - bool m_ignorePrinterMargins{false}; - bool m_isAutoCropLength{false}; - bool m_isAutoCropWidth{false}; - bool m_isUnitePages{false}; - QString m_layoutPrinterName{}; - bool m_isLayoutStale{false}; - QMarginsF m_tiledMargins{}; + QString m_fileName{}; + QSizeF m_layoutPaperSize{}; + QMarginsF m_layoutMargins{}; + QWidget *m_parentWidget{nullptr}; + bool m_isLayoutPortrait{true}; + bool m_ignorePrinterMargins{false}; + bool m_isAutoCropLength{false}; + bool m_isAutoCropWidth{false}; + bool m_isUnitePages{false}; + QString m_layoutPrinterName{}; + bool m_isLayoutStale{false}; + QMarginsF m_tiledMargins{}; PageOrientation m_tiledPDFOrientation{PageOrientation::Portrait}; - QSizeF m_tiledPDFPaperSize{}; - QString m_watermarkPath{}; + QSizeF m_tiledPDFPaperSize{}; + QString m_watermarkPath{}; + bool m_togetherWithNotches{false}; + QList m_layoutPapers{}; + QList m_layoutScenes{}; + QList m_layoutShadows{}; + QList> m_layoutDetails{}; - QList m_layoutPapers{}; - QList m_layoutScenes{}; - QList m_layoutShadows{}; - QList > m_layoutDetails{}; - - bool m_isTiled{false}; + bool m_isTiled{false}; qreal m_xscale{1}; qreal m_yscale{1}; @@ -380,13 +389,13 @@ inline void VPrintLayout::SetLayoutShadows(const QList &layoutS } //--------------------------------------------------------------------------------------------------------------------- -inline auto VPrintLayout::LayoutDetails() const -> QList > +inline auto VPrintLayout::LayoutDetails() const -> QList> { return m_layoutDetails; } //--------------------------------------------------------------------------------------------------------------------- -inline void VPrintLayout::SetLayoutDetails(const QList > &layoutDetails) +inline void VPrintLayout::SetLayoutDetails(const QList> &layoutDetails) { m_layoutDetails = layoutDetails; } @@ -426,4 +435,17 @@ inline void VPrintLayout::SetWatermarkPath(const QString &watermarkPath) { m_watermarkPath = watermarkPath; } + +//--------------------------------------------------------------------------------------------------------------------- +inline void VPrintLayout::SetBoundaryTogetherWithNotches(bool value) +{ + m_togetherWithNotches = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +inline auto VPrintLayout::IsBoundaryTogetherWithNotches() const -> bool +{ + return m_togetherWithNotches; +} + #endif // VPRINTLAYOUT_H diff --git a/src/libs/vmisc/commandoptions.cpp b/src/libs/vmisc/commandoptions.cpp index b29f9aae0..9cd3af847 100644 --- a/src/libs/vmisc/commandoptions.cpp +++ b/src/libs/vmisc/commandoptions.cpp @@ -133,6 +133,7 @@ const QString LONG_OPTION_LANDSCAPE_ORIENTATION = QStringLiteral("landscapeOrien const QString LONG_OPTION_NEST_QUANTITY = QStringLiteral("nestQuantity"); const QString LONG_OPTION_PREFER_ONE_SHEET_SOLUTION = QStringLiteral("preferOneSheetSolution"); +const QString LONG_OPTION_BOUNDARY_TOGETHER_WITH_NOTCHES = QStringLiteral("boundaryTogetherWithNotches"); //--------------------------------------------------------------------------------------------------------------------- /** @@ -212,5 +213,6 @@ auto AllKeys() -> QStringList LONG_OPTION_MANUAL_PRIORITY, LONG_OPTION_LANDSCAPE_ORIENTATION, LONG_OPTION_NEST_QUANTITY, - LONG_OPTION_PREFER_ONE_SHEET_SOLUTION}; + LONG_OPTION_PREFER_ONE_SHEET_SOLUTION, + LONG_OPTION_BOUNDARY_TOGETHER_WITH_NOTCHES}; } diff --git a/src/libs/vmisc/commandoptions.h b/src/libs/vmisc/commandoptions.h index 8612925de..295a12a60 100644 --- a/src/libs/vmisc/commandoptions.h +++ b/src/libs/vmisc/commandoptions.h @@ -130,6 +130,7 @@ extern const QString LONG_OPTION_MANUAL_PRIORITY; extern const QString LONG_OPTION_LANDSCAPE_ORIENTATION; extern const QString LONG_OPTION_NEST_QUANTITY; extern const QString LONG_OPTION_PREFER_ONE_SHEET_SOLUTION; +extern const QString LONG_OPTION_BOUNDARY_TOGETHER_WITH_NOTCHES; auto AllKeys() -> QStringList; diff --git a/src/libs/vmisc/vvalentinasettings.cpp b/src/libs/vmisc/vvalentinasettings.cpp index 902d59754..b600e2171 100644 --- a/src/libs/vmisc/vvalentinasettings.cpp +++ b/src/libs/vmisc/vvalentinasettings.cpp @@ -74,6 +74,9 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPatternRememberMaterials, ("patt // NOLINTNEXTLINE Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPatternBackgroundImageDefOpacity, ("pattern/backgroundImageDefOpacity"_L1)) +// NOLINTNEXTLINE +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingPatternBoundaryTogetherWithNotches, + ("pattern/boundaryTogetherWithNotches"_L1)) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutWidth, ("layout/width"_L1)) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutSorting, ("layout/sorting"_L1)) // NOLINT @@ -90,6 +93,9 @@ Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutAutoCropWidth, ("layout/au Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutSaveLength, ("layout/saveLength"_L1)) // NOLINT // NOLINTNEXTLINE Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutPreferOneSheetSolution, ("layout/preferOneSheetSolution"_L1)) +// NOLINTNEXTLINE +Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutBoundaryTogetherWithNotches, + ("layout/boundaryTogetherWithNotches"_L1)) Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutUnitePages, ("layout/unitePages"_L1)) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingLayoutShowGrainline, ("layout/showGrainline"_L1)) // NOLINT Q_GLOBAL_STATIC_WITH_ARGS(const QString, settingFields, ("layout/fields"_L1)) // NOLINT @@ -454,6 +460,24 @@ void VValentinaSettings::SetLayoutPreferOneSheetSolution(bool value) setValue(*settingLayoutPreferOneSheetSolution, value); } +//--------------------------------------------------------------------------------------------------------------------- +auto VValentinaSettings::GetLayoutBoundaryTogetherWithNotches() const -> bool +{ + return value(*settingLayoutBoundaryTogetherWithNotches, GetDefLayoutBoundaryTogetherWithNotches()).toBool(); +} + +//--------------------------------------------------------------------------------------------------------------------- +auto VValentinaSettings::GetDefLayoutBoundaryTogetherWithNotches() -> bool +{ + return false; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VValentinaSettings::SetLayoutBoundaryTogetherWithNotches(bool value) +{ + setValue(*settingLayoutBoundaryTogetherWithNotches, value); +} + //--------------------------------------------------------------------------------------------------------------------- auto VValentinaSettings::GetLayoutUnitePages() const -> bool { @@ -1045,6 +1069,18 @@ void VValentinaSettings::SetUseToolGroups(bool value) setValue(*settingConfigurationUseToolGroups, value); } +//--------------------------------------------------------------------------------------------------------------------- +auto VValentinaSettings::IsBoundaryTogetherWithNotches() const -> bool +{ + return value(*settingPatternBoundaryTogetherWithNotches, false).toBool(); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VValentinaSettings::SetBoundaryTogetherWithNotches(bool value) +{ + setValue(*settingPatternBoundaryTogetherWithNotches, value); +} + //--------------------------------------------------------------------------------------------------------------------- template auto VValentinaSettings::GetCachedValue(T &cache, const QString &setting, T defValue, T valueMin, T valueMax) const -> T diff --git a/src/libs/vmisc/vvalentinasettings.h b/src/libs/vmisc/vvalentinasettings.h index 4ed3fcfd9..b7f697eeb 100644 --- a/src/libs/vmisc/vvalentinasettings.h +++ b/src/libs/vmisc/vvalentinasettings.h @@ -115,6 +115,10 @@ public: static auto GetDefLayoutPreferOneSheetSolution() -> bool; void SetLayoutPreferOneSheetSolution(bool value); + auto GetLayoutBoundaryTogetherWithNotches() const -> bool; + static auto GetDefLayoutBoundaryTogetherWithNotches() -> bool; + void SetLayoutBoundaryTogetherWithNotches(bool value); + auto GetLayoutUnitePages() const -> bool; static auto GetDefLayoutUnitePages() -> bool; void SetLayoutUnitePages(bool value); @@ -250,6 +254,9 @@ public: auto IsUseToolGroups() const -> bool; void SetUseToolGroups(bool value); + auto IsBoundaryTogetherWithNotches() const -> bool; + void SetBoundaryTogetherWithNotches(bool value); + private: Q_DISABLE_COPY_MOVE(VValentinaSettings) // NOLINT diff --git a/src/libs/vpatterndb/vpassmark.cpp b/src/libs/vpatterndb/vpassmark.cpp index d37bfc56a..93e47ee62 100644 --- a/src/libs/vpatterndb/vpassmark.cpp +++ b/src/libs/vpatterndb/vpassmark.cpp @@ -550,14 +550,14 @@ auto CreateCheckMarkPassmark(const VPiecePassmarkData &passmarkData, const QLine if (width > 0) { // clockwise QLineF l1(line.p2(), line.p1()); - l1.setAngle(l1.angle() - angle); + l1.setAngle(l1.angle() + angle); l1 = VPassmark::FindIntersection(l1, seamAllowance); return {{l1.p2(), l1.p1()}, {line.p2(), line.p1()}}; } QLineF l2(line.p2(), line.p1()); - l2.setAngle(l2.angle() + angle); + l2.setAngle(l2.angle() - angle); l2 = VPassmark::FindIntersection(l2, seamAllowance); return {line, l2}; diff --git a/src/libs/vpatterndb/vpassmark.h b/src/libs/vpatterndb/vpassmark.h index 1a7552267..71a9a1bf1 100644 --- a/src/libs/vpatterndb/vpassmark.h +++ b/src/libs/vpatterndb/vpassmark.h @@ -28,15 +28,15 @@ #ifndef VPASSMARK_H #define VPASSMARK_H -#include #include +#include -#include "vpiece.h" #include "../vmisc/typedef.h" +#include "vpiece.h" class QPainterPath; -enum class PassmarkStatus: qint8 +enum class PassmarkStatus : qint8 { Error = 0, Common = 1, @@ -48,22 +48,22 @@ QT_WARNING_DISABLE_GCC("-Weffc++") struct VPiecePassmarkData { - VSAPoint previousSAPoint{}; // NOLINT(misc-non-private-member-variables-in-classes) - VSAPoint passmarkSAPoint{}; // NOLINT(misc-non-private-member-variables-in-classes) - VSAPoint nextSAPoint{}; // NOLINT(misc-non-private-member-variables-in-classes) - qreal saWidth{0}; // NOLINT(misc-non-private-member-variables-in-classes) - QString nodeName{}; // NOLINT(misc-non-private-member-variables-in-classes) - QString pieceName{}; // NOLINT(misc-non-private-member-variables-in-classes) - PassmarkLineType passmarkLineType{// NOLINT(misc-non-private-member-variables-in-classes) - PassmarkLineType::OneLine}; - PassmarkAngleType passmarkAngleType{// NOLINT(misc-non-private-member-variables-in-classes) - PassmarkAngleType::Straightforward}; - bool isMainPathNode{true}; // NOLINT(misc-non-private-member-variables-in-classes) - bool isShowSecondPassmark{true}; // NOLINT(misc-non-private-member-variables-in-classes) - vsizetype passmarkIndex{-1}; // NOLINT(misc-non-private-member-variables-in-classes) - vidtype id{NULL_ID}; // NOLINT(misc-non-private-member-variables-in-classes) - qreal globalPassmarkLength{0}; // NOLINT(misc-non-private-member-variables-in-classes) - qreal globalPassmarkWidth{0}; // NOLINT(misc-non-private-member-variables-in-classes) + VSAPoint previousSAPoint{}; // NOLINT(misc-non-private-member-variables-in-classes) + VSAPoint passmarkSAPoint{}; // NOLINT(misc-non-private-member-variables-in-classes) + VSAPoint nextSAPoint{}; // NOLINT(misc-non-private-member-variables-in-classes) + qreal saWidth{0}; // NOLINT(misc-non-private-member-variables-in-classes) + QString nodeName{}; // NOLINT(misc-non-private-member-variables-in-classes) + QString pieceName{}; // NOLINT(misc-non-private-member-variables-in-classes) + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + PassmarkLineType passmarkLineType{PassmarkLineType::OneLine}; + // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) + PassmarkAngleType passmarkAngleType{PassmarkAngleType::Straightforward}; + bool isMainPathNode{true}; // NOLINT(misc-non-private-member-variables-in-classes) + bool isShowSecondPassmark{true}; // NOLINT(misc-non-private-member-variables-in-classes) + vsizetype passmarkIndex{-1}; // NOLINT(misc-non-private-member-variables-in-classes) + vidtype id{NULL_ID}; // NOLINT(misc-non-private-member-variables-in-classes) + qreal globalPassmarkLength{0}; // NOLINT(misc-non-private-member-variables-in-classes) + qreal globalPassmarkWidth{0}; // NOLINT(misc-non-private-member-variables-in-classes) auto toJson() const -> QJsonObject; }; @@ -73,7 +73,12 @@ Q_DECLARE_TYPEINFO(VPiecePassmarkData, Q_MOVABLE_TYPE); // NOLINT QT_WARNING_POP -enum class PassmarkSide : qint8 { All=0, Left=1, Right=2 }; +enum class PassmarkSide : qint8 +{ + All = 0, + Left = 1, + Right = 2 +}; class VPassmark { @@ -102,6 +107,7 @@ public: static auto FindIntersection(const QLineF &line, const QVector &seamAllowance) -> QLineF; static const qreal passmarkRadiusFactor; + private: VPiecePassmarkData m_data{}; bool m_null{true}; diff --git a/src/libs/vpatterndb/vpiece.cpp b/src/libs/vpatterndb/vpiece.cpp index df723c7e7..75f8833a1 100644 --- a/src/libs/vpatterndb/vpiece.cpp +++ b/src/libs/vpatterndb/vpiece.cpp @@ -247,7 +247,7 @@ auto VPiece::Passmarks(const VContainer *data) const -> QVector const QVector unitedPath = GetUnitedPath(data); if (not IsSeamAllowance() || not IsPassmarksPossible(unitedPath)) { - return QVector(); + return {}; } QVector passmarks; @@ -693,7 +693,7 @@ auto VPiece::SeamAllowancePointsWithRotation(const VContainer *data, vsizetype m const VPiecePath path = data->GetPiecePath(records.at(recordIndex).path); QVector r = path.SeamAllowancePoints(data, width, records.at(recordIndex).reverse); - for (auto & j : r) + for (auto &j : r) { j.SetAngleType(PieceNodeAngle::ByLengthCurve); j.SetSABefore(0); diff --git a/src/libs/vtools/tools/vtoolseamallowance.cpp b/src/libs/vtools/tools/vtoolseamallowance.cpp index 27ec1f154..e2e6a9d71 100644 --- a/src/libs/vtools/tools/vtoolseamallowance.cpp +++ b/src/libs/vtools/tools/vtoolseamallowance.cpp @@ -38,12 +38,19 @@ #include "../undocommands/movepiece.h" #include "../undocommands/savepieceoptions.h" #include "../undocommands/togglepiecestate.h" +#include "../vformat/vlabeltemplate.h" #include "../vgeometry/varc.h" #include "../vgeometry/vellipticalarc.h" #include "../vgeometry/vplacelabelitem.h" #include "../vgeometry/vpointf.h" +#include "../vlayout/vboundary.h" +#include "../vlayout/vlayoutpiece.h" +#include "../vlayout/vlayoutpiecepath.h" +#include "../vmisc/theme/themeDef.h" #include "../vmisc/theme/vscenestylesheet.h" +#include "../vmisc/vvalentinasettings.h" #include "../vpatterndb/calculator.h" +#include "../vpatterndb/floatItemData/vgrainlinedata.h" #include "../vpatterndb/floatItemData/vpatternlabeldata.h" #include "../vpatterndb/floatItemData/vpiecelabeldata.h" #include "../vpatterndb/variables/vincrement.h" @@ -54,14 +61,6 @@ #include "../vwidgets/vmaingraphicsview.h" #include "../vwidgets/vnobrushscalepathitem.h" #include "../vwidgets/vpiecegrainline.h" -#include "theme/themeDef.h" -#include "toolsdef.h" -#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0) -#include "../vmisc/backport/qoverload.h" -#endif // QT_VERSION < QT_VERSION_CHECK(5, 7, 0) -#include "../vformat/vlabeltemplate.h" -#include "../vpatterndb/floatItemData/vgrainlinedata.h" -#include "../vpatterndb/floatItemData/vpiecelabeldata.h" #include "nodeDetails/vnodearc.h" #include "nodeDetails/vnodeellipticalarc.h" #include "nodeDetails/vnodepoint.h" @@ -70,6 +69,11 @@ #include "nodeDetails/vtoolpiecepath.h" #include "nodeDetails/vtoolpin.h" #include "nodeDetails/vtoolplacelabel.h" +#include "toolsdef.h" + +#if QT_VERSION < QT_VERSION_CHECK(5, 7, 0) +#include "../vmisc/backport/qoverload.h" +#endif // QT_VERSION < QT_VERSION_CHECK(5, 7, 0) #include #include @@ -77,6 +81,7 @@ #include #include #include +#include #include #include #include @@ -1460,16 +1465,86 @@ void VToolSeamAllowance::RefreshGeometry(bool updateChildren) const VPiece detail = VAbstractTool::data.GetPiece(m_id); - QFuture futurePath = QtConcurrent::run([this, detail]() { return detail.MainPathPath(getData()); }); - QFuture futurePassmarks = - QtConcurrent::run([this, detail]() { return detail.PassmarksPath(getData()); }); + VValentinaSettings *settings = VAbstractValApplication::VApp()->ValentinaSettings(); + const bool combineTogether = settings->IsBoundaryTogetherWithNotches(); - QFuture> futureSeamAllowance; + QFuture futurePath = QtConcurrent::run( + [this, detail, combineTogether]() + { + if (combineTogether) + { + const QVector passmarks = VLayoutPiece::ConvertPassmarks(detail, getData()); + const QVector points = detail.MainPathPoints(getData()); + + bool seamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + bool builtInSeamAllowance = detail.IsSeamAllowance() && detail.IsSeamAllowanceBuiltIn(); + + VBoundary boundary(points, seamAllowance, builtInSeamAllowance); + boundary.SetPieceName(detail.GetName()); + const QList sequence = boundary.Combine(passmarks, false, false); + + QVector combinedBoundary; + for (const auto &item : sequence) + { + const auto path = item.item.value().Points(); + QVector convertedPoints; + CastTo(path, convertedPoints); + combinedBoundary += convertedPoints; + } + + QPainterPath combinedPath; + combinedPath.addPolygon(QPolygonF(combinedBoundary)); + combinedPath.closeSubpath(); + combinedPath.setFillRule(Qt::OddEvenFill); + + return combinedPath; + } + + return detail.MainPathPath(getData()); + }); + + QFuture futurePassmarks; + if (!combineTogether) + { + futurePassmarks = QtConcurrent::run([this, detail]() { return detail.PassmarksPath(getData()); }); + } + + QFuture futureSeamAllowance; QFuture futureSeamAllowanceValid; - if (detail.IsSeamAllowance()) + if (detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn()) { - futureSeamAllowance = QtConcurrent::run([this, detail]() { return detail.SeamAllowancePoints(getData()); }); + futureSeamAllowance = QtConcurrent::run( + [this, detail, combineTogether]() + { + if (combineTogether) + { + const QVector passmarks = VLayoutPiece::ConvertPassmarks(detail, getData()); + const QVector points = detail.SeamAllowancePoints(getData()); + + VBoundary boundary(points, true); + boundary.SetPieceName(detail.GetName()); + const QList sequence = boundary.Combine(passmarks, false, false); + + QVector combinedBoundary; + for (const auto &item : sequence) + { + const auto path = item.item.value().Points(); + QVector convertedPoints; + CastTo(path, convertedPoints); + combinedBoundary += convertedPoints; + } + + QPainterPath combinedPath; + combinedPath.addPolygon(QPolygonF(combinedBoundary)); + combinedPath.closeSubpath(); + combinedPath.setFillRule(Qt::OddEvenFill); + + return combinedPath; + } + + return detail.SeamAllowancePath(getData()); + }); futureSeamAllowanceValid = QtConcurrent::run([this, detail]() { return detail.IsSeamAllowanceValid(getData()); }); } @@ -1506,7 +1581,7 @@ void VToolSeamAllowance::RefreshGeometry(bool updateChildren) ? throw VException(errorMsg) : qWarning() << VAbstractValApplication::warningMessageSignature + errorMsg; } - path.addPath(detail.SeamAllowancePath(futureSeamAllowance.result())); + path.addPath(futureSeamAllowance.result()); path.setFillRule(Qt::OddEvenFill); m_seamAllowance->setPath(path); @@ -1548,7 +1623,7 @@ void VToolSeamAllowance::RefreshGeometry(bool updateChildren) } } - m_passmarks->setPath(futurePassmarks.result()); + m_passmarks->setPath(!combineTogether ? futurePassmarks.result() : QPainterPath()); this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); diff --git a/src/libs/vtools/undocommands/label/movelabel.cpp b/src/libs/vtools/undocommands/label/movelabel.cpp index bb207bfb5..db4567835 100644 --- a/src/libs/vtools/undocommands/label/movelabel.cpp +++ b/src/libs/vtools/undocommands/label/movelabel.cpp @@ -33,16 +33,15 @@ #include "../ifc/ifcdef.h" #include "../ifc/xml/vabstractpattern.h" #include "../vmisc/def.h" -#include "../vmisc/vabstractapplication.h" +#include "../vmisc/vabstractvalapplication.h" +#include "../vtools/tools/vabstracttool.h" #include "../vundocommand.h" #include "moveabstractlabel.h" -#include "../vtools/tools/vabstracttool.h" -#include "../vwidgets/vmaingraphicsview.h" //--------------------------------------------------------------------------------------------------------------------- MoveLabel::MoveLabel(VAbstractPattern *doc, const QPointF &pos, const quint32 &id, QUndoCommand *parent) - : MoveAbstractLabel(doc, id, pos, parent), - m_scene(VAbstractValApplication::VApp()->getCurrentScene()) + : MoveAbstractLabel(doc, id, pos, parent), + m_scene(VAbstractValApplication::VApp()->getCurrentScene()) { setText(tr("move point label")); @@ -64,7 +63,7 @@ MoveLabel::MoveLabel(VAbstractPattern *doc, const QPointF &pos, const quint32 &i //--------------------------------------------------------------------------------------------------------------------- auto MoveLabel::mergeWith(const QUndoCommand *command) -> bool { - const MoveLabel *moveCommand = static_cast(command); + const auto *moveCommand = static_cast(command); SCASSERT(moveCommand != nullptr) if (moveCommand->GetPointId() != nodeId) @@ -97,7 +96,7 @@ void MoveLabel::Do(const QPointF &pos) doc->SetAttribute(domElement, AttrMx, QString().setNum(VAbstractValApplication::VApp()->fromPixel(pos.x()))); doc->SetAttribute(domElement, AttrMy, QString().setNum(VAbstractValApplication::VApp()->fromPixel(pos.y()))); - if (VAbstractTool *tool = qobject_cast(VAbstractPattern::getTool(nodeId))) + if (auto *tool = qobject_cast(VAbstractPattern::getTool(nodeId))) { tool->ChangeLabelPosition(nodeId, pos); }