New feature. Boundary together with notches.

This commit is contained in:
Roman Telezhynskyi 2023-11-28 16:40:27 +02:00
parent fef322116b
commit 5724c9611a
72 changed files with 2670 additions and 692 deletions

View file

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

View file

@ -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 <The unit>"

View file

@ -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 <The unit>"

View file

@ -259,6 +259,12 @@ void VPCarrousel::SetOrientation(Qt::Orientation orientation)
RefreshOrientation();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::RefreshPieceMiniature()
{
ui->listWidget->Refresh();
}
//---------------------------------------------------------------------------------------------------------------------
void VPCarrousel::RefreshOrientation()
{

View file

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

View file

@ -32,6 +32,7 @@
#include <QMenu>
#include <QPainter>
#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();

View file

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

View file

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

View file

@ -28,16 +28,17 @@
#ifndef VPLAYOUTSETTINGS_H
#define VPLAYOUTSETTINGS_H
#include <QCoreApplication>
#include <QMarginsF>
#include <QSizeF>
#include <QString>
#include <QCoreApplication>
#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

View file

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

View file

@ -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<VLayoutPoint> 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<VLayoutPassmark> 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<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
QVector<QPointF> combinedBoundary;
for (const auto &item : sequence)
{
m_seamLine.lineTo(seamLinePoints.at(i));
const auto path = item.item.value<VLayoutPiecePath>().Points();
QVector<QPointF> 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<QPointF> 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<VLayoutPoint> 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<VLayoutPassmark> 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<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
QVector<QPointF> combinedBoundary;
for (const auto &item : sequence)
{
m_cuttingLine.lineTo(cuttingLinepoints.at(i));
const auto path = item.item.value<VLayoutPiecePath>().Points();
QVector<QPointF> 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<QPointF> 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<VLayoutPassmark> passmarks = piece->GetMappedPassmarks();
for (auto &passmark : passmarks)
{

View file

@ -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<VPSheetPtr> sheets = m_layout->GetAllSheets();
for (const auto &sheet : sheets)
{
if (sheet.isNull())
{
continue;
}
QList<VPPiecePtr> 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()

View file

@ -297,6 +297,8 @@ private slots:
void UpdateShortcuts();
void TogetherWithNotchesChanged(bool checked);
private:
Q_DISABLE_COPY_MOVE(VPMainWindow) // NOLINT
Ui::VPMainWindow *ui;

View file

@ -1715,6 +1715,13 @@
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxTogetherWithNotches">
<property name="text">
<string>Boundary together with notches</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
@ -2427,8 +2434,8 @@
</resources>
<connections/>
<buttongroups>
<buttongroup name="buttonGroupRotationDirection"/>
<buttongroup name="buttonGroupSheetOrientation"/>
<buttongroup name="buttonGroupTileOrientation"/>
<buttongroup name="buttonGroupSheetOrientation"/>
<buttongroup name="buttonGroupRotationDirection"/>
</buttongroups>
</ui>

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -340,6 +340,29 @@
</layout>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxTogetherWithNotches">
<property name="text">
<string>Boundary together with notches</string>
</property>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Debug</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_7">
<item>
<widget class="QCheckBox" name="checkBoxShowLayoutAllowance">
<property name="text">
<string>Show layout allowance</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer">
<property name="orientation">

View file

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

View file

@ -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<std::pair<QString, LayoutExportFormats> >;
static auto InitFormats() -> QVector<std::pair<QString, LayoutExportFormats>>;
void RemoveFormatFromList(LayoutExportFormats format);

View file

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>544</width>
<height>401</height>
<height>439</height>
</rect>
</property>
<property name="windowTitle">
@ -138,7 +138,14 @@
<string>Show grainline</string>
</property>
<property name="checked">
<bool>true</bool>
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxTogetherWithNotches">
<property name="text">
<string>Boundary together with notches</string>
</property>
</widget>
</item>
@ -275,7 +282,7 @@
</size>
</property>
<property name="text">
<string notr="true"></string>
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../../../libs/vmisc/share/resources/icon.qrc">
@ -482,7 +489,7 @@
<item>
<widget class="QToolButton" name="toolButtonPortrait">
<property name="text">
<string notr="true"></string>
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../../../libs/vmisc/share/resources/icon.qrc">
@ -502,7 +509,7 @@
<item>
<widget class="QToolButton" name="toolButtonLandscape">
<property name="text">
<string notr="true"></string>
<string notr="true"/>
</property>
<property name="icon">
<iconset resource="../../../libs/vmisc/share/resources/icon.qrc">

View file

@ -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<quint32> ids = pattern->DataPieces()->keys();
const bool updateChildren = false;
QGuiApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
for (const auto &id : ids)
{
try
{
if (auto *tool = qobject_cast<VToolSeamAllowance *>(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<DialogSaveLayout>(new DialogSaveLayout(
static_cast<int>(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<DialogSaveLayout>(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();

View file

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

View file

@ -115,6 +115,7 @@
<addaction name="actionInteractiveTools"/>
<addaction name="actionShowCurveDetails"/>
<addaction name="actionShowMainPath"/>
<addaction name="actionBoundaryTogetherWithNotches"/>
<addaction name="actionShowAccuracyRadius"/>
<addaction name="separator"/>
<addaction name="actionAddBackgroundImage"/>
@ -2611,6 +2612,17 @@
<enum>QAction::NoRole</enum>
</property>
</action>
<action name="actionBoundaryTogetherWithNotches">
<property name="checkable">
<bool>true</bool>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Boundary together with notches</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>

View file

@ -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<VLayoutPiece> &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<VLayoutPiece> &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<VLayoutPiece> &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<VLayoutPiece> &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<VLayoutPiece> 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<QGraphicsScene *> &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)
{

View file

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

View file

@ -103,6 +103,7 @@
<file>schema/layout/v0.1.4.xsd</file>
<file>schema/layout/v0.1.5.xsd</file>
<file>schema/layout/v0.1.6.xsd</file>
<file>schema/layout/v0.1.7.xsd</file>
<file>schema/known_measurements/v1.0.0.xsd</file>
</qresource>
</RCC>

View file

@ -0,0 +1,590 @@
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="layout">
<xs:complexType>
<xs:sequence>
<xs:element name="properties">
<xs:complexType>
<xs:sequence>
<xs:element type="units" name="unit"/>
<xs:element type="xs:string" name="title"/>
<xs:element type="xs:string" name="description"/>
<xs:element name="control">
<xs:complexType>
<xs:attribute type="xs:boolean" name="warningSuperposition"/>
<xs:attribute type="xs:boolean" name="warningOutOfBound"/>
<xs:attribute type="xs:boolean" name="stickyEdges"/>
<xs:attribute type="xs:boolean" name="followGrainline"/>
<xs:attribute type="xs:boolean" name="boundaryTogetherWithNotches"/>
<xs:attribute type="xs:float" name="piecesGap"/>
</xs:complexType>
</xs:element>
<xs:element name="tiles">
<xs:complexType>
<xs:sequence>
<xs:element name="size">
<xs:complexType>
<xs:attribute type="xs:float" name="width" use="required"/>
<xs:attribute type="xs:float" name="length" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="margin">
<xs:complexType>
<xs:attribute type="xs:float" name="top"/>
<xs:attribute type="xs:float" name="right"/>
<xs:attribute type="xs:float" name="bottom"/>
<xs:attribute type="xs:float" name="left"/>
<xs:attribute type="xs:boolean" name="ignoreMargins"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="visible"/>
<xs:attribute type="xs:string" name="matchingMarks"/>
<xs:attribute type="xs:boolean" name="printScheme"/>
<xs:attribute type="xs:boolean" name="tileNumber"/>
</xs:complexType>
</xs:element>
<xs:element name="scale">
<xs:complexType>
<xs:attribute type="LayoutScale" name="xScale"/>
<xs:attribute type="LayoutScale" name="yScale"/>
</xs:complexType>
</xs:element>
<xs:element name="watermark">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="showPreview" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="unplacedPieces">
<xs:complexType>
<xs:sequence>
<xs:element name="piece" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="seamLine">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="3" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="seamAllowance">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="grainline">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="LinePathOrEmpty">
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="ArrowDirection" name="arrowDirection" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="notches">
<xs:complexType>
<xs:sequence>
<xs:element name="notch" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
<xs:attribute type="NotchType" name="type" use="optional"/>
<xs:attribute type="LinePath" name="baseLine" use="optional"/>
<xs:attribute type="LinesPath" name="path" use="optional"/>
<xs:attribute type="xs:boolean" name="clockwiseOpening" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="internalPaths">
<xs:complexType>
<xs:sequence>
<xs:element name="internalPath" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="2" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="cut" use="optional"/>
<xs:attribute type="CurvePenStyle" name="penStyle" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="markers">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="marker" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:attribute type="Transformation" name="transform" use="required"/>
<xs:attribute type="MarkerType" name="type" use="required"/>
<xs:attribute type="PointPath" name="center" use="required"/>
<xs:attribute type="RectPath" name="box" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="labels">
<xs:complexType>
<xs:sequence>
<xs:element name="pieceLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
<xs:attribute type="xs:string" name="svgFont"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="shape" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="patternLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
<xs:attribute type="xs:string" name="svgFont"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="shape" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="uid" type="uuid" use="required"/>
<xs:attribute type="xs:string" name="name"/>
<xs:attribute type="xs:boolean" name="mirrored"/>
<xs:attribute type="xs:boolean" name="forbidFlipping"/>
<xs:attribute type="xs:boolean" name="forceFlipping"/>
<xs:attribute type="xs:boolean" name="followGrainline"/>
<xs:attribute type="xs:boolean" name="sewLineOnDrawing"/>
<xs:attribute type="Transformation" name="transform"/>
<xs:attribute type="xs:string" name="gradationLabel"/>
<xs:attribute type="xs:unsignedInt" name="copyNumber"/>
<xs:attribute type="xs:boolean" name="showSeamline"/>
<xs:attribute type="xs:float" name="xScale"/>
<xs:attribute type="xs:float" name="yScale"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="sheets">
<xs:complexType>
<xs:sequence>
<xs:element name="sheet" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name"/>
<xs:element name="size">
<xs:complexType>
<xs:attribute type="xs:float" name="width" use="required"/>
<xs:attribute type="xs:float" name="length" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="margin">
<xs:complexType>
<xs:attribute type="xs:float" name="top"/>
<xs:attribute type="xs:float" name="right"/>
<xs:attribute type="xs:float" name="bottom"/>
<xs:attribute type="xs:float" name="left"/>
<xs:attribute type="xs:boolean" name="ignoreMargins"/>
</xs:complexType>
</xs:element>
<xs:element name="pieces">
<xs:complexType>
<xs:sequence>
<xs:element name="piece" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="seamLine">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="3" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="seamAllowance">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="grainline">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="LinePathOrEmpty">
<xs:attribute type="xs:boolean" name="enabled" use="optional"/>
<xs:attribute type="ArrowDirection" name="arrowDirection" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
<xs:element name="notches">
<xs:complexType>
<xs:sequence>
<xs:element name="notch" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:boolean" name="builtIn" use="optional"/>
<xs:attribute type="NotchType" name="type" use="optional"/>
<xs:attribute type="LinePath" name="baseLine" use="optional"/>
<xs:attribute type="LinesPath" name="path" use="optional"/>
<xs:attribute type="xs:boolean" name="clockwiseOpening" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="internalPaths">
<xs:complexType>
<xs:sequence>
<xs:element name="internalPath" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="point" minOccurs="2" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute type="xs:double" name="x" use="required"/>
<xs:attribute type="xs:double" name="y" use="required"/>
<xs:attribute type="xs:boolean" name="turnPoint" use="optional"/>
<xs:attribute type="xs:boolean" name="curvePoint" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:boolean" name="cut" use="optional"/>
<xs:attribute type="CurvePenStyle" name="penStyle" use="optional"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="markers">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="marker" maxOccurs="unbounded" minOccurs="0">
<xs:complexType>
<xs:attribute type="Transformation" name="transform" use="required"/>
<xs:attribute type="MarkerType" name="type" use="required"/>
<xs:attribute type="PointPath" name="center" use="required"/>
<xs:attribute type="RectPath" name="box" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="labels">
<xs:complexType>
<xs:sequence>
<xs:element name="pieceLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="AlignmentType" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
<xs:attribute type="xs:string" name="svgFont"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="PathNotEmpty" name="shape" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="patternLabel" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:sequence>
<xs:element name="lines">
<xs:complexType>
<xs:sequence>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:boolean" name="bold" use="optional"/>
<xs:attribute type="xs:boolean" name="italic" use="optional"/>
<xs:attribute type="AlignmentType" name="alignment" use="optional"/>
<xs:attribute type="xs:unsignedInt" name="fontSize" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="font"/>
<xs:attribute type="xs:string" name="svgFont"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="PathNotEmpty" name="shape" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="uid" type="uuid" use="required"/>
<xs:attribute type="xs:string" name="name"/>
<xs:attribute type="xs:boolean" name="mirrored"/>
<xs:attribute type="xs:boolean" name="forbidFlipping"/>
<xs:attribute type="xs:boolean" name="forceFlipping"/>
<xs:attribute type="xs:boolean" name="followGrainline"/>
<xs:attribute type="xs:boolean" name="sewLineOnDrawing"/>
<xs:attribute type="Transformation" name="transform"/>
<xs:attribute type="xs:string" name="gradationLabel"/>
<xs:attribute type="xs:unsignedInt" name="copyNumber"/>
<xs:attribute type="xs:boolean" name="showSeamline"/>
<xs:attribute type="xs:float" name="xScale"/>
<xs:attribute type="xs:float" name="yScale"/>
<xs:attribute type="xs:float" name="zValue"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="GrainlineType" name="grainlineType"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="formatVersion" name="version" use="required"/>
</xs:complexType>
</xs:element>
<!--Types-->
<xs:simpleType name="formatVersion">
<xs:restriction base="xs:string">
<xs:pattern value="[0-9]{1,}\.[0-9]{1,}\.[0-9]{1,}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="units">
<xs:restriction base="xs:string">
<xs:enumeration value="mm"/>
<xs:enumeration value="cm"/>
<xs:enumeration value="inch"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="uuid">
<xs:restriction base="xs:string">
<xs:pattern value="|\{[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}\}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="ArrowDirection">
<xs:restriction base="xs:string">
<xs:enumeration value="oneWayUp"/>
<xs:enumeration value="oneWayDown"/>
<xs:enumeration value="twoWaysUpDown"/>
<xs:enumeration value="fourWays"/>
<xs:enumeration value="twoWaysUpLeft"/>
<xs:enumeration value="twoWaysUpRight"/>
<xs:enumeration value="twoWaysDownLeft"/>
<xs:enumeration value="twoWaysDownRight"/>
<xs:enumeration value="threeWaysUpDownLeft"/>
<xs:enumeration value="threeWaysUpDownRight"/>
<xs:enumeration value="threeWaysUpLeftRight"/>
<xs:enumeration value="threeWaysDownLeftRight"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="NotchType">
<xs:restriction base="xs:unsignedInt">
<!--OneLine-->
<xs:enumeration value="0"/>
<!--TwoLines-->
<xs:enumeration value="1"/>
<!--ThreeLines-->
<xs:enumeration value="2"/>
<!--TMark-->
<xs:enumeration value="3"/>
<!--VMark-->
<xs:enumeration value="4"/>
<!--VMark2-->
<xs:enumeration value="5"/>
<!--UMark-->
<xs:enumeration value="6"/>
<!--BoxMark-->
<xs:enumeration value="7"/>
<!--CheckMark-->
<xs:enumeration value="8"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="CurvePenStyle">
<xs:restriction base="xs:string">
<xs:enumeration value="hair"/>
<xs:enumeration value="dashLine"/>
<xs:enumeration value="dotLine"/>
<xs:enumeration value="dashDotLine"/>
<xs:enumeration value="dashDotDotLine"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="MarkerType">
<xs:restriction base="xs:unsignedInt">
<xs:enumeration value="0"/><!--Segment-->
<xs:enumeration value="1"/><!--Rectangle-->
<xs:enumeration value="2"/><!--Cross-->
<xs:enumeration value="3"/><!--Tshaped-->
<xs:enumeration value="4"/><!--Doubletree-->
<xs:enumeration value="5"/><!--Corner-->
<xs:enumeration value="6"/><!--Triangle-->
<xs:enumeration value="7"/><!--Hshaped-->
<xs:enumeration value="8"/><!--Button-->
<xs:enumeration value="9"/><!--Circle-->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="AlignmentType">
<xs:restriction base="xs:unsignedInt">
<xs:enumeration value="0"/><!--default (no aligns)-->
<xs:enumeration value="1"/><!--aligns with the left edge-->
<xs:enumeration value="2"/><!--aligns with the right edge-->
<xs:enumeration value="4"/><!--Centers horizontally in the available space-->
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Transformation">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?;){8,}[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PathNotEmpty">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?\s){0,}[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PathOrEmpty">
<xs:restriction base="xs:string">
<xs:pattern value="|([-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?\s){0,}[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LinePathOrEmpty">
<xs:restriction base="xs:string">
<xs:pattern value="|[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LinePath">
<xs:restriction base="xs:string">
<xs:pattern value="[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LinesPath">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?\*){0,}[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?;[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="PointPath">
<xs:restriction base="xs:string">
<xs:pattern value="[-+]?\d+\.?\d*([eE][-+]?\d+)?,[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="RectPath">
<xs:restriction base="xs:string">
<xs:pattern value="([-+]?\d+\.?\d*([eE][-+]?\d+)?;){3,}[-+]?\d+\.?\d*([eE][-+]?\d+)?"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="GrainlineType">
<xs:restriction base="xs:string">
<xs:enumeration value="horizontal"/>
<xs:enumeration value="vertical"/>
<xs:enumeration value="notFixed"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="LayoutScale">
<xs:restriction base="xs:float">
<xs:minInclusive value="0.01"/>
<xs:maxInclusive value="3"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

View file

@ -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<unsigned int, QString>
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();
}

View file

@ -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<unsigned, QString>;
@ -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

View file

@ -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<dx_ifaceBlock> &detailBl
{
QVector<VLayoutPoint> points = PieceOutline(detail);
if (m_togetherWithNotches)
{
const QVector<VLayoutPassmark> 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<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
points.clear();
for (const auto &item : sequence)
{
const auto path = item.item.value<VLayoutPiecePath>().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<dx_ifaceBlock> &detailBl
//---------------------------------------------------------------------------------------------------------------------
void VDxfEngine::ExportAAMADraw(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail)
{
if (detail.IsSeamAllowance() && not detail.IsHideMainPath() && not detail.IsSeamAllowanceBuiltIn())
{
QVector<VLayoutPoint> 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<QVector<VLayoutPoint>> drawIntLine = detail.MappedInternalPathsForCut(false);
for (const auto &intLine : drawIntLine)
@ -827,6 +852,49 @@ void VDxfEngine::ExportAAMADraw(const QSharedPointer<dx_ifaceBlock> &detailBlock
}
}
//---------------------------------------------------------------------------------------------------------------------
void VDxfEngine::ExportAAMADrawSewLine(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail)
{
if (detail.IsSeamAllowance() && not detail.IsHideMainPath() && not detail.IsSeamAllowanceBuiltIn())
{
const UTF8STRING &layer = not detail.IsSewLineOnDrawing() ? *layer14 : *layer8;
QVector<VLayoutPoint> points = detail.GetMappedContourPoints();
auto DrawPolygon = [this, detailBlock, layer](const QVector<VLayoutPoint> &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<VLayoutPassmark> 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<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, true, false);
for (const auto &item : sequence)
{
const auto path = item.item.value<VLayoutPiecePath>().Points();
DrawPolygon(path, false);
}
}
else
{
DrawPolygon(points, true);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VDxfEngine::ExportAAMAIntcut(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail)
{
@ -846,7 +914,7 @@ void VDxfEngine::ExportAAMAIntcut(const QSharedPointer<dx_ifaceBlock> &detailBlo
//---------------------------------------------------------------------------------------------------------------------
void VDxfEngine::ExportAAMANotch(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail)
{
if (detail.IsSeamAllowance())
if (detail.IsSeamAllowance() && !m_togetherWithNotches)
{
const QVector<VLayoutPassmark> passmarks = detail.GetMappedPassmarks();
for (const auto &passmark : passmarks)
@ -1001,6 +1069,28 @@ void VDxfEngine::ExportASTMPieceBoundary(const QSharedPointer<dx_ifaceBlock> &de
{
QVector<VLayoutPoint> pieceBoundary = PieceOutline(detail);
if (m_togetherWithNotches)
{
const QVector<VLayoutPassmark> 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<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
pieceBoundary.clear();
for (const auto &item : sequence)
{
const auto path = item.item.value<VLayoutPiecePath>().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<dx_ifaceBlock> &detailBl
{
QVector<VLayoutPoint> sewLine = detail.GetMappedContourPoints();
// Sew lines
if (DRW_Entity *e = AAMAPolygon(sewLine, *layer14, true))
auto DrawPolygon = [this, detailBlock](const QVector<VLayoutPoint> &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<VLayoutPassmark> 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<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, true, false);
for (const auto &item : sequence)
{
const auto path = item.item.value<VLayoutPiecePath>().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<dx_ifaceBlock> &detailBloc
//---------------------------------------------------------------------------------------------------------------------
void VDxfEngine::ExportASTMNotches(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail)
{
if (!detail.IsSeamAllowance())
if (!detail.IsSeamAllowance() || m_togetherWithNotches)
{
return;
}

View file

@ -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<VLayoutPiece> &details) -> bool;
void ExportAAMAOutline(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMADraw(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMADrawSewLine(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMAIntcut(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMANotch(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);
void ExportAAMAGrainline(const QSharedPointer<dx_ifaceBlock> &detailBlock, const VLayoutPiece &detail);

View file

@ -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<VLayoutPiece> &details) const -> bool
{

View file

@ -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<VLayoutPiece> &details) const -> bool;
auto ExportToASTM(const QVector<VLayoutPiece> &details) const -> bool;

View file

@ -415,74 +415,6 @@ auto VAbstractCurve::IsPointOnCurve(const QPointF &p) const -> bool
return IsPointOnCurve(GetPoints(), p);
}
//---------------------------------------------------------------------------------------------------------------------
auto VAbstractCurve::SubdividePath(const QVector<QPointF> &points, QPointF p, QVector<QPointF> &sub1,
QVector<QPointF> &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
{

View file

@ -78,9 +78,6 @@ public:
static auto IsPointOnCurve(const QVector<QPointF> &points, const QPointF &p) -> bool;
auto IsPointOnCurve(const QPointF &p) const -> bool;
static auto SubdividePath(const QVector<QPointF> &points, QPointF p, QVector<QPointF> &sub1, QVector<QPointF> &sub2)
-> bool;
auto ClosestPoint(QPointF scenePoint) const -> QPointF;
virtual auto GetStartAngle() const -> qreal = 0;

View file

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

View file

@ -29,9 +29,9 @@
#ifndef VGEOMETRYDEF_H
#define VGEOMETRYDEF_H
#include <QVector>
#include <QPolygonF>
#include <QTransform>
#include <QVector>
#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;

View file

@ -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<QPoint> points) -> QVector<QPoint>
{
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<QPoint> path) -> QVector<QPoint>
{
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<QPoint> 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 <class T> inline auto CastToPoint(const QVector<T> &points) -> QVector<QPoint>
{
@ -464,7 +376,7 @@ void VHPGLEngine::ExportDetails(QTextStream &out, const QList<VLayoutPiece> &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<QPoint> points = CastToPoint(ConvertPath(detail.GetMappedContourPoints()));
QVector<VLayoutPoint> sewLine = detail.GetMappedContourPoints();
if (m_togetherWithNotches)
{
const QVector<VLayoutPassmark> 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<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, true, false);
for (const auto &item : sequence)
{
const auto path = CastToPoint(ConvertPath(item.item.value<VLayoutPiecePath>().Points()));
PlotPath(out, path, Qt::SolidLine);
}
}
else
{
QVector<QPoint> 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<VLayoutPoint> pieceBoundary = detail.IsSeamAllowance() && not detail.IsSeamAllowanceBuiltIn()
? detail.GetMappedSeamAllowancePoints()
: detail.GetMappedContourPoints();
if (m_togetherWithNotches)
{
const QVector<VLayoutPassmark> 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<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
pieceBoundary.clear();
for (const auto &item : sequence)
{
const auto path = CastToPoint(ConvertPath(item.item.value<VLayoutPiecePath>().Points()));
PlotPath(out, path, Qt::SolidLine);
}
}
else
{
QVector<QPoint> 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<QPoint> 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<VLayoutPassmark> passmarks = detail.GetMappedPassmarks();
for (const auto &passmark : passmarks)
{
@ -710,7 +671,6 @@ void VHPGLEngine::PlotLabelOutlineFont(QTextStream &out, const VLayoutPiece &det
}
//---------------------------------------------------------------------------------------------------------------------
template <class T> auto VHPGLEngine::ConvertPath(const QVector<T> &path) const -> QVector<T>
{
QVector<T> convertedPath;
@ -740,8 +700,6 @@ void VHPGLEngine::PlotPath(QTextStream &out, QVector<QPoint> path, Qt::PenStyle
return;
}
path = OptimizePath(path);
if (penStyle != Qt::SolidLine && penStyle != Qt::DashLine && penStyle != Qt::DotLine &&
penStyle != Qt::DashDotLine && penStyle != Qt::DashDotDotLine)
{

View file

@ -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<VLayoutPiece> &details) -> QList<VLayoutPiece>;
@ -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<VLayoutPiece> &details) -> bool;
auto GenerateHPGL2(const QVector<VLayoutPiece> &details) -> bool;
@ -110,7 +114,7 @@ private:
void ExportDetails(QTextStream &out, const QList<VLayoutPiece> &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

View file

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

View file

@ -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<VLayoutPiece> &details) const -> bool;
auto ExportToHPGL2(const QVector<VLayoutPiece> &details) const -> bool;

View file

@ -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 <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QLine>
#include <QLineF>
#include <QPainterPath>
#include <QSet>

View file

@ -139,9 +139,10 @@ public:
static auto LabelShapePath(const VLayoutPlaceLabel &label) -> QPainterPath;
static auto LabelShapePath(const PlaceLabelImg &shape) -> QPainterPath;
protected:
template <class T>
static auto RemoveDublicates(const QVector<T> &points, bool removeFirstAndLast = true) -> QVector<T>;
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 <class T>

View file

@ -28,13 +28,13 @@
#include "vbank.h"
#include <climits>
#include <QLoggingCategory>
#include <climits>
#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 <rpcndr.h>
// #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<uint, QHash<int, qint64>> &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<uint> 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<int, qint64> usortedGroup = unsorted.value(priority);
QHash<int, qint64>::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<int, qint64> usortedGroup = unsorted.value(priority);
QHash<int, qint64>::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

View file

@ -30,31 +30,33 @@
#define VBANK_H
#include <QHash>
#include <QLoggingCategory>
#include <QMap>
#include <QRectF>
#include <QVector>
#include <QtGlobal>
#include <QLoggingCategory>
#include "../vmisc/typedef.h"
#include "vlayoutpiece.h"
#include "vlayoutdef.h"
#include "vlayoutpiece.h"
// An annoying char define, from the Windows team in <rpcndr.h>
// #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<uint, QMultiMap<qint64, int>> &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

View file

@ -0,0 +1,644 @@
/************************************************************************
**
** @file vboundary.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#include "vboundary.h"
#include "../ifc/exception/vexception.h"
#include "../vgeometry/vgobject.h"
#include "../vmisc/vabstractapplication.h"
#include "vlayoutpiecepath.h"
#include <QPoint>
#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<VBoundarySequenceItemData> &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<VLayoutPoint> &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<VLayoutPoint>>
{
QVector<VLayoutPoint> 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<VLayoutPoint> shape2;
shape2.append(TurnPoint(line2.p1()));
shape2.append(TurnPoint(line2.p2()));
return {shape1, shape2};
}
//---------------------------------------------------------------------------------------------------------------------
auto PrepareNoneBreakingPassmarkShape(const VLayoutPassmark &passmark) -> QVector<QVector<VLayoutPoint>>
{
auto TurnPoint = [](QPointF point)
{
VLayoutPoint p(point);
p.SetTurnPoint(true);
return p;
};
QVector<VLayoutPoint> 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<QVector<VLayoutPoint>>
{
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<QLineF> lines = passmark.lines;
if (lines.size() < 3)
{
return {};
}
QLineF line1 = lines.takeFirst();
QVector<VLayoutPoint> 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<VLayoutPoint> 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<QVector<VLayoutPoint>>
{
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<VBoundarySequenceItemData> &notchSequence)
{
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<VBoundarySequenceItemData> &notchSequence)
{
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<VLayoutPoint> &boundary, const QPointF &p, QVector<VLayoutPoint> &sub1,
QVector<VLayoutPoint> &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<QPointF>(boundary.at(i)),
static_cast<QPointF>(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<VBoundarySequenceItemData> &sequence, int i, const VBoundarySequenceItemData &item,
bool drawMode) -> bool
{
auto passmark = item.item.value<VLayoutPassmark>();
bool inserted = false;
const auto boundary = sequence.at(i).item.value<VLayoutPiecePath>().Points();
QVector<VLayoutPoint> sub1;
QVector<VLayoutPoint> 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<QVector<VLayoutPoint>> 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<VBoundarySequenceItemData> &sequence, int i, const VBoundarySequenceItemData &item,
bool drawMode) -> bool
{
auto passmark = item.item.value<VLayoutPassmark>();
QVector<QVector<VLayoutPoint>> shape = PreparePassmarkShape(passmark, drawMode);
if (shape.isEmpty())
{
return false;
}
const QVector<VLayoutPoint> &subShape = shape.constFirst();
if (subShape.size() < 2)
{
return false;
}
const auto boundary = sequence.at(i).item.value<VLayoutPiecePath>().Points();
QVector<VLayoutPoint> startSub1;
QVector<VLayoutPoint> startSub2;
if (!SubdividePath(boundary, subShape.constFirst(), startSub1, startSub2))
{
return false;
}
QVector<VLayoutPoint> endSub1;
QVector<VLayoutPoint> 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<VLayoutPoint> &boundary, bool seamAllowance, bool builtInSeamAllowance)
: m_boundary(boundary),
m_seamAllowance(seamAllowance),
m_builtInSeamAllowance(builtInSeamAllowance)
{
}
//---------------------------------------------------------------------------------------------------------------------
auto VBoundary::Combine(const QVector<VLayoutPassmark> &passmarks, bool drawMode, bool layoutAllowance) const
-> QList<VBoundarySequenceItemData>
{
QList<VBoundarySequenceItemData> 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<VBoundarySequenceItemData> 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<VBoundarySequenceItemData> &sequence,
bool drawMode) const
{
auto passmark = item.item.value<VLayoutPassmark>();
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;
}
}

View file

@ -0,0 +1,85 @@
/************************************************************************
**
** @file vboundary.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @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
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
**
** Valentina is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** Valentina is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
**
*************************************************************************/
#ifndef VBOUNDARY_H
#define VBOUNDARY_H
#include "../vgeometry/vgeometrydef.h"
#include "vlayoutpoint.h"
#include <QCoreApplication>
#include <QList>
#include <QVariant>
#include <QVector>
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<VLayoutPoint> &boundary, bool seamAllowance, bool builtInSeamAllowance = false);
auto Combine(const QVector<VLayoutPassmark> &passmarks, bool drawMode, bool layoutAllowance = false) const
-> QList<VBoundarySequenceItemData>;
void SetPieceName(const QString &newPieceName);
private:
QVector<VLayoutPoint> 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<VBoundarySequenceItemData> &sequence,
bool drawMode) const;
};
//---------------------------------------------------------------------------------------------------------------------
inline void VBoundary::SetPieceName(const QString &newPieceName)
{
m_pieceName = newPieceName;
}
#endif // VBOUNDARY_H

View file

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

View file

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

View file

@ -324,6 +324,7 @@ void VLayoutExporter::ExportToAAMADXF(const QVector<VLayoutPiece> &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<VLayoutPiece> &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<VLayoutPiece> &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<VLayoutPiece> &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.");

View file

@ -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<QGraphicsItem *> &details) const;
void ExportToPNG(QGraphicsScene *scene, const QList<QGraphicsItem *> &details) const;
void ExportToTIF(QGraphicsScene *scene, const QList<QGraphicsItem *> &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<QGraphicsItem *> &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
{

View file

@ -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<QGraphicsItem *>
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<QList<QGraphicsItem *
list.reserve(papers.count());
for (const auto &paper : papers)
{
list.append(paper.GetItemDetails(IsTestAsPaths()));
list.append(paper.GetItemDetails(textAsPaths, togetherWithNotches, showLayoutAllowance));
}
return list;
}
@ -390,6 +366,30 @@ void VLayoutGenerator::SetTextAsPaths(bool value)
textAsPaths = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutGenerator::IsBoundaryTogetherWithNotches() const -> 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;
}
//---------------------------------------------------------------------------------------------------------------------

View file

@ -29,30 +29,30 @@
#ifndef VLAYOUTGENERATOR_H
#define VLAYOUTGENERATOR_H
#include <QList>
#include <QMargins>
#include <QMetaObject>
#include <QObject>
#include <QString>
#include <QVector>
#include <QtGlobal>
#include <memory>
#include <atomic>
#include <QMargins>
#include <memory>
#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<VLayoutPiece> &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<VLayoutPaper> 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<VLayoutPaper> 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<QList<VLayoutPiece> > &nDetails, qreal length, int i) const;
void UniteDetails(int j, QList<QList<VLayoutPiece>> &nDetails, qreal length, int i) const;
void UnitePapers(int j, QList<qreal> &papersLength, qreal length);
auto MoveDetails(qreal length, const QVector<VLayoutPiece> &details) const -> QList<VLayoutPiece>;
auto MasterPage() const -> VLayoutPaper;

View file

@ -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<QGraphicsScene> scene(new QGraphicsScene());
QList<QGraphicsItem *> list = GetItemDetails(textAsPaths);
QList<QGraphicsItem *> 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<QGraphicsItem *>
auto VLayoutPaper::GetItemDetails(bool textAsPaths, bool togetherWithNotches, bool showLayoutAllowance) const
-> QList<QGraphicsItem *>
{
QList<QGraphicsItem *> 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;
}

View file

@ -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<QGraphicsItem *>;
Q_REQUIRED_RESULT auto GetItemDetails(bool textAsPaths, bool togetherWithNotches, bool showLayoutAllowance) const
-> QList<QGraphicsItem *>;
auto GetDetails() const -> QVector<VLayoutPiece>;
void SetDetails(const QVector<VLayoutPiece> &details);

View file

@ -39,6 +39,7 @@
#include <QMessageLogger>
#include <QPainterPath>
#include <QPoint>
#include <QPolygon>
#include <QPolygonF>
#include <QTransform>
#include <QUuid>
@ -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<VPieceNode> 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<VLayoutPassmark>
{
const QVector<VPassmark> passmarks = piece.Passmarks(pattern);
QVector<VLayoutPassmark> 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<QString, QString>
{
@ -640,7 +564,8 @@ auto VLayoutPiece::Create(const VPiece &piece, vidtype id, const VContainer *pat
QFuture<QVector<VLayoutPoint>> futureMainPath =
QtConcurrent::run([piece, pattern]() { return piece.MainPathPoints(pattern); });
QFuture<QVector<VLayoutPiecePath>> futureInternalPaths = QtConcurrent::run(ConvertInternalPaths, piece, pattern);
QFuture<QVector<VLayoutPassmark>> futurePassmarks = QtConcurrent::run(ConvertPassmarks, piece, pattern);
QFuture<QVector<VLayoutPassmark>> futurePassmarks =
QtConcurrent::run(VLayoutPiece::ConvertPassmarks, piece, pattern);
QFuture<QVector<VLayoutPlaceLabel>> 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<VSAPoint> 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<VLayoutPoint> pieceBoundary = IsSeamAllowance() && not IsSeamAllowanceBuiltIn()
? GetMappedSeamAllowancePoints()
: GetMappedContourPoints();
QVector<QPointF> points;
CastTo(GetSeamAllowancePoints(), points);
d->m_square = qFloor(qAbs(SumTrapezoids(points) / 2.0));
if (togetherWithNotches)
{
const QVector<VLayoutPassmark> passmarks = GetMappedPassmarks();
bool seamAllowance = IsSeamAllowance() && !IsSeamAllowanceBuiltIn();
bool builtInSeamAllowance = IsSeamAllowance() && IsSeamAllowanceBuiltIn();
VBoundary boundary(pieceBoundary, seamAllowance, builtInSeamAllowance);
boundary.SetPieceName(GetName());
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, true);
pieceBoundary.clear();
for (const auto &item : sequence)
{
pieceBoundary += item.item.value<VLayoutPiecePath>().Points();
}
}
else
{
QVector<VSAPoint> 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<QPointF> points;
CastTo(GetContourPoints(), points);
d->m_square = qFloor(qAbs(SumTrapezoids(points) / 2.0));
}
QVector<VSAPoint> 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<QPointF> 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<VLayoutPiecePath> &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<VBoundarySequenceItemData> sequence = boundary.Combine(d->m_passmarks, true, false);
for (const auto &item : sequence)
{
const auto itemPath = item.item.value<VLayoutPiecePath>().Points();
QVector<QPointF> 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<VLayoutPoint> 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<VBoundarySequenceItemData> 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<VLayoutPiecePath>().Points();
QVector<QPointF> convertedPoints;
CastTo(itemPath, convertedPoints);
path.addPolygon(QPolygonF(convertedPoints));
}
}
else
{
ekv.lineTo(points.at(i));
}
QVector<VLayoutPoint> 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<VLayoutPassmark> 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<VLayoutPoint> base =
(IsSeamAllowance() && not IsSeamAllowanceBuiltIn()) ? d->m_seamAllowance : d->m_contour;
if (togetherWithNotches)
{
const QVector<VLayoutPassmark> passmarks = GetMappedPassmarks();
bool seamAllowance = IsSeamAllowance() && !IsSeamAllowanceBuiltIn();
bool builtInSeamAllowance = IsSeamAllowance() && IsSeamAllowanceBuiltIn();
VBoundary boundary(base, seamAllowance, builtInSeamAllowance);
boundary.SetPieceName(GetName());
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, true);
base.clear();
for (const auto &item : sequence)
{
base += item.item.value<VLayoutPiecePath>().Points();
}
base = VAbstractPiece::RemoveDublicates(base, false);
}
QVector<QPointF> points;
CastTo(base, points);
return VAbstractPiece::IsAllowanceValid(points, d->m_layoutAllowance);
@ -1820,13 +1809,13 @@ auto VLayoutPiece::DetailPath() const -> QVector<VLayoutPoint>
}
//---------------------------------------------------------------------------------------------------------------------
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 <class T> auto VLayoutPiece::Map(QVector<T> points) const -> QVector<T>
{
return MapVector(points, d->m_matrix, d->m_mirror);
}
//---------------------------------------------------------------------------------------------------------------------
auto VLayoutPiece::ConvertPassmarks(const VPiece &piece, const VContainer *pattern) -> QVector<VLayoutPassmark>
{
const QVector<VPassmark> passmarks = piece.Passmarks(pattern);
QVector<VLayoutPassmark> 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;
}

View file

@ -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<VLayoutPassmark>;
auto GetUniqueID() const -> QString override;
@ -109,7 +110,7 @@ public:
auto GetMappedLayoutAllowancePoints() const -> QVector<QPointF>;
auto GetLayoutAllowancePoints() const -> QVector<QPointF>;
void SetLayoutAllowancePoints();
void SetLayoutAllowancePoints(bool togetherWithNotches);
auto GetMappedExternalContourPoints() const -> QVector<VLayoutPoint>;
auto GetExternalContourPoints() const -> QVector<VLayoutPoint>;
@ -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<VLayoutPoint>;
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<QPointF> &labelShape, const VTextManager &tm,

View file

@ -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<QGraphicsItem *>;
void SetLayoutShadows(const QList<QGraphicsItem *> &layoutShadows);
auto LayoutDetails() const -> QList<QList<QGraphicsItem *> >;
void SetLayoutDetails(const QList<QList<QGraphicsItem *> > &layoutDetails);
auto LayoutDetails() const -> QList<QList<QGraphicsItem *>>;
void SetLayoutDetails(const QList<QList<QGraphicsItem *>> &layoutDetails);
void SetBoundaryTogetherWithNotches(bool value);
auto IsBoundaryTogetherWithNotches() const -> bool;
void PrintTiled();
void PrintOrigin();
@ -125,34 +134,34 @@ public:
static auto PrinterScaleDiff(QPrinter *printer) -> QPair<qreal, qreal>;
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<QGraphicsItem *> m_layoutPapers{};
QList<QGraphicsScene *> m_layoutScenes{};
QList<QGraphicsItem *> m_layoutShadows{};
QList<QList<QGraphicsItem *>> m_layoutDetails{};
QList<QGraphicsItem *> m_layoutPapers{};
QList<QGraphicsScene *> m_layoutScenes{};
QList<QGraphicsItem *> m_layoutShadows{};
QList<QList<QGraphicsItem *> > 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<QGraphicsItem *> &layoutS
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPrintLayout::LayoutDetails() const -> QList<QList<QGraphicsItem *> >
inline auto VPrintLayout::LayoutDetails() const -> QList<QList<QGraphicsItem *>>
{
return m_layoutDetails;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VPrintLayout::SetLayoutDetails(const QList<QList<QGraphicsItem *> > &layoutDetails)
inline void VPrintLayout::SetLayoutDetails(const QList<QList<QGraphicsItem *>> &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

View file

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

View file

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

View file

@ -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 <typename T>
auto VValentinaSettings::GetCachedValue(T &cache, const QString &setting, T defValue, T valueMin, T valueMax) const -> T

View file

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

View file

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

View file

@ -28,15 +28,15 @@
#ifndef VPASSMARK_H
#define VPASSMARK_H
#include <QtGlobal>
#include <QMetaType>
#include <QtGlobal>
#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<QPointF> &seamAllowance) -> QLineF;
static const qreal passmarkRadiusFactor;
private:
VPiecePassmarkData m_data{};
bool m_null{true};

View file

@ -247,7 +247,7 @@ auto VPiece::Passmarks(const VContainer *data) const -> QVector<VPassmark>
const QVector<VPieceNode> unitedPath = GetUnitedPath(data);
if (not IsSeamAllowance() || not IsPassmarksPossible(unitedPath))
{
return QVector<VPassmark>();
return {};
}
QVector<VPassmark> passmarks;
@ -693,7 +693,7 @@ auto VPiece::SeamAllowancePointsWithRotation(const VContainer *data, vsizetype m
const VPiecePath path = data->GetPiecePath(records.at(recordIndex).path);
QVector<VSAPoint> r = path.SeamAllowancePoints(data, width, records.at(recordIndex).reverse);
for (auto & j : r)
for (auto &j : r)
{
j.SetAngleType(PieceNodeAngle::ByLengthCurve);
j.SetSABefore(0);

View file

@ -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 <QFuture>
#include <QGraphicsSceneMouseEvent>
@ -77,6 +81,7 @@
#include <QKeyEvent>
#include <QMenu>
#include <QMessageBox>
#include <QPainterPath>
#include <QTimer>
#include <QUuid>
#include <QtConcurrent/QtConcurrentRun>
@ -1460,16 +1465,86 @@ void VToolSeamAllowance::RefreshGeometry(bool updateChildren)
const VPiece detail = VAbstractTool::data.GetPiece(m_id);
QFuture<QPainterPath> futurePath = QtConcurrent::run([this, detail]() { return detail.MainPathPath(getData()); });
QFuture<QPainterPath> futurePassmarks =
QtConcurrent::run([this, detail]() { return detail.PassmarksPath(getData()); });
VValentinaSettings *settings = VAbstractValApplication::VApp()->ValentinaSettings();
const bool combineTogether = settings->IsBoundaryTogetherWithNotches();
QFuture<QVector<VLayoutPoint>> futureSeamAllowance;
QFuture<QPainterPath> futurePath = QtConcurrent::run(
[this, detail, combineTogether]()
{
if (combineTogether)
{
const QVector<VLayoutPassmark> passmarks = VLayoutPiece::ConvertPassmarks(detail, getData());
const QVector<VLayoutPoint> 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<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
QVector<QPointF> combinedBoundary;
for (const auto &item : sequence)
{
const auto path = item.item.value<VLayoutPiecePath>().Points();
QVector<QPointF> 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<QPainterPath> futurePassmarks;
if (!combineTogether)
{
futurePassmarks = QtConcurrent::run([this, detail]() { return detail.PassmarksPath(getData()); });
}
QFuture<QPainterPath> futureSeamAllowance;
QFuture<bool> 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<VLayoutPassmark> passmarks = VLayoutPiece::ConvertPassmarks(detail, getData());
const QVector<VLayoutPoint> points = detail.SeamAllowancePoints(getData());
VBoundary boundary(points, true);
boundary.SetPieceName(detail.GetName());
const QList<VBoundarySequenceItemData> sequence = boundary.Combine(passmarks, false, false);
QVector<QPointF> combinedBoundary;
for (const auto &item : sequence)
{
const auto path = item.item.value<VLayoutPiecePath>().Points();
QVector<QPointF> 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);

View file

@ -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<const MoveLabel *>(command);
const auto *moveCommand = static_cast<const MoveLabel *>(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<VAbstractTool *>(VAbstractPattern::getTool(nodeId)))
if (auto *tool = qobject_cast<VAbstractTool *>(VAbstractPattern::getTool(nodeId)))
{
tool->ChangeLabelPosition(nodeId, pos);
}