Move piece position validation to separate thread.
This commit is contained in:
parent
a8a75f358a
commit
537efbeaa8
|
@ -276,7 +276,7 @@ auto VPLayout::AddSheet(const VPSheetPtr &sheet) -> VPSheetPtr
|
|||
if (not sheet.isNull() && GetSheet(sheet->Uuid()).isNull())
|
||||
{
|
||||
m_sheets.append(sheet);
|
||||
connect(this, &VPLayout::PieceTransformationChanged, sheet.data(), &VPSheet::CheckPiecePositionValidity);
|
||||
connect(this, &VPLayout::PieceTransformationChanged, sheet.data(), &VPSheet::CheckPiecesPositionValidity);
|
||||
}
|
||||
return sheet;
|
||||
}
|
||||
|
@ -328,7 +328,7 @@ void VPLayout::SetFocusedSheet(const VPSheetPtr &focusedSheet)
|
|||
m_focusedSheet = focusedSheet.isNull() ? m_sheets.constFirst() : focusedSheet;
|
||||
}
|
||||
|
||||
CheckPiecesPositionValidity(m_focusedSheet);
|
||||
m_focusedSheet->CheckPiecesPositionValidity();
|
||||
|
||||
emit ActiveSheetChanged(m_focusedSheet);
|
||||
}
|
||||
|
@ -427,30 +427,9 @@ void VPLayout::CheckPiecesPositionValidity() const
|
|||
{
|
||||
for (const auto &sheet : m_sheets)
|
||||
{
|
||||
CheckPiecesPositionValidity(sheet);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPLayout::CheckPiecesPositionValidity(const VPSheetPtr &sheet) const
|
||||
{
|
||||
if (not sheet.isNull())
|
||||
{
|
||||
const VPLayoutSettings &settings = LayoutSettings();
|
||||
|
||||
if (settings.GetWarningPiecesOutOfBound())
|
||||
if (not sheet.isNull())
|
||||
{
|
||||
sheet->ValidatePiecesOutOfBound();
|
||||
}
|
||||
|
||||
if (settings.GetWarningSuperpositionOfPieces())
|
||||
{
|
||||
sheet->ValidateSuperpositionOfPieces();
|
||||
}
|
||||
|
||||
if (settings.GetWarningPieceGapePosition())
|
||||
{
|
||||
sheet->ValidatePieceGapePosition();
|
||||
sheet->CheckPiecesPositionValidity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,6 @@ public:
|
|||
void Clear();
|
||||
|
||||
void CheckPiecesPositionValidity() const;
|
||||
void CheckPiecesPositionValidity(const VPSheetPtr &sheet) const;
|
||||
|
||||
auto TileFactory() const -> QSharedPointer<VPTileFactory>;
|
||||
void SetTileFactory(const QSharedPointer<VPTileFactory> &newTileFactory);
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace
|
|||
{
|
||||
constexpr qreal minStickyDistance = MmToPixel(3.);
|
||||
constexpr qreal maxStickyDistance = MmToPixel(15.);
|
||||
constexpr qreal stickyShift = MmToPixel(1.);
|
||||
constexpr qreal stickyShift = MmToPixel(5.);
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto CutEdge(const QLineF &edge) -> QVector<QPointF>
|
||||
|
@ -440,24 +440,15 @@ auto VPPiece::PrepareStickyPath(const QVector<QPointF> &path) -> QVector<QPointF
|
|||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPPiece::ClosestDistance(const QVector<QPointF> &path1, const QVector<QPointF> &path2) -> QLineF
|
||||
{
|
||||
std::function<QLineF(const QPointF &)> const DistanceFunc = [path2](const QPointF &p1)
|
||||
const int maxThreads = QThread::idealThreadCount();
|
||||
|
||||
QVector<QVector<QPointF>> path1Chunks;
|
||||
path1Chunks.reserve(maxThreads);
|
||||
const vsizetype chunkSize = (path1.size() + maxThreads - 1) / maxThreads; // Round up
|
||||
for (vsizetype i = 0; i < path1.size(); i += chunkSize)
|
||||
{
|
||||
qreal minLocalDistance = std::numeric_limits<qreal>::max();
|
||||
QLineF localClosestDistance;
|
||||
|
||||
for (const auto &p2 : path2)
|
||||
{
|
||||
QLineF const d(p1, p2);
|
||||
qreal const length = d.length();
|
||||
if (length < minLocalDistance)
|
||||
{
|
||||
minLocalDistance = length;
|
||||
localClosestDistance = d;
|
||||
}
|
||||
}
|
||||
|
||||
return localClosestDistance;
|
||||
};
|
||||
path1Chunks.append(path1.mid(i, chunkSize));
|
||||
}
|
||||
|
||||
std::function<void(QLineF &, const QLineF &)> const ReduceFunc = [](QLineF &result, const QLineF &next)
|
||||
{
|
||||
|
@ -469,7 +460,29 @@ auto VPPiece::ClosestDistance(const QVector<QPointF> &path1, const QVector<QPoin
|
|||
}
|
||||
};
|
||||
|
||||
return QtConcurrent::blockingMappedReduced<QLineF>(path1, DistanceFunc, ReduceFunc);
|
||||
auto CalculateClosestDistanceForChunk = [&](const QVector<QPointF> &chunk) -> QLineF
|
||||
{
|
||||
qreal minLocalDistance = std::numeric_limits<qreal>::max();
|
||||
QLineF localClosestDistance;
|
||||
|
||||
for (const auto &c : chunk)
|
||||
{
|
||||
for (const auto &p2 : path2)
|
||||
{
|
||||
QLineF const d(c, p2);
|
||||
qreal const length = d.length();
|
||||
if (length < minLocalDistance)
|
||||
{
|
||||
minLocalDistance = length;
|
||||
localClosestDistance = d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return localClosestDistance;
|
||||
};
|
||||
|
||||
return QtConcurrent::blockingMappedReduced<QLineF>(path1Chunks, CalculateClosestDistanceForChunk, ReduceFunc);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -38,6 +38,205 @@
|
|||
#include "vplayout.h"
|
||||
#include "vppiece.h"
|
||||
|
||||
#include <QtConcurrent>
|
||||
|
||||
namespace
|
||||
{
|
||||
struct VSheetPiece
|
||||
{
|
||||
QString m_id{};
|
||||
bool m_showFullPiece{false};
|
||||
QLineF m_seamMirrorLine{};
|
||||
QLineF m_seamAllowanceMirrorLine{};
|
||||
QVector<QPointF> m_externalContourPoints{};
|
||||
};
|
||||
|
||||
struct VPiecesValidationData
|
||||
{
|
||||
bool m_warnPiecesOutOfBound{false};
|
||||
bool m_warnSuperpositionOfPieces{false};
|
||||
bool m_warnPieceGapePosition{false};
|
||||
bool m_cutOnFold{false};
|
||||
QRectF m_sheetRect{};
|
||||
qreal m_pieceGap{0};
|
||||
QVector<VSheetPiece> m_pieces{};
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void ValidatePiecesOutOfBound(const VPiecesValidationData &data, QHash<QString, VPiecePositionValidity> &validations)
|
||||
{
|
||||
|
||||
for (const auto &piece : data.m_pieces)
|
||||
{
|
||||
VPiecePositionValidity validation = validations.value(piece.m_id);
|
||||
|
||||
if (data.m_cutOnFold && not piece.m_showFullPiece && !piece.m_seamMirrorLine.isNull())
|
||||
{
|
||||
QLineF const foldLine = data.m_sheetRect.width() >= data.m_sheetRect.height()
|
||||
? QLineF(data.m_sheetRect.topLeft(), data.m_sheetRect.topRight())
|
||||
: QLineF(data.m_sheetRect.topRight(), data.m_sheetRect.bottomRight());
|
||||
|
||||
validation.m_outOfBound =
|
||||
not VGObject::IsLineSegmentOnLineSegment(foldLine, piece.m_seamAllowanceMirrorLine, MmToPixel(0.5));
|
||||
}
|
||||
else
|
||||
{
|
||||
QRectF const pieceRect = VLayoutPiece::BoundingRect(piece.m_externalContourPoints);
|
||||
validation.m_outOfBound = not data.m_sheetRect.contains(pieceRect);
|
||||
}
|
||||
|
||||
validations.insert(piece.m_id, validation);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void ValidateSuperpositionOfPieces(const VPiecesValidationData &data,
|
||||
QHash<QString, VPiecePositionValidity> &validations)
|
||||
{
|
||||
QSet<QString> invalidPieces;
|
||||
invalidPieces.reserve(data.m_pieces.size());
|
||||
|
||||
for (const auto &piece : data.m_pieces)
|
||||
{
|
||||
if (invalidPieces.contains(piece.m_id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool hasSuperposition = false;
|
||||
VSheetPiece invalidPiece;
|
||||
|
||||
for (const auto &p : data.m_pieces)
|
||||
{
|
||||
if (piece.m_id == p.m_id)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (VPPiece::PathsSuperposition(piece.m_externalContourPoints, p.m_externalContourPoints))
|
||||
{
|
||||
hasSuperposition = true;
|
||||
invalidPiece = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto UpdateValidity = [&validations, hasSuperposition, &invalidPieces](const QString &id)
|
||||
{
|
||||
VPiecePositionValidity validation = validations.value(id);
|
||||
validation.m_superposition = hasSuperposition;
|
||||
validations.insert(id, validation);
|
||||
if (hasSuperposition)
|
||||
{
|
||||
invalidPieces.insert(id);
|
||||
}
|
||||
};
|
||||
|
||||
UpdateValidity(piece.m_id);
|
||||
|
||||
if (!invalidPiece.m_id.isEmpty())
|
||||
{
|
||||
UpdateValidity(invalidPiece.m_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void ValidatePiecesGapePosition(const VPiecesValidationData &data, QHash<QString, VPiecePositionValidity> &validations)
|
||||
{
|
||||
if (data.m_pieceGap <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
QSet<QString> invalidPieces;
|
||||
invalidPieces.reserve(data.m_pieces.size());
|
||||
|
||||
for (const auto &piece : data.m_pieces)
|
||||
{
|
||||
if (invalidPieces.contains(piece.m_id))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QRectF const path1Rect = VLayoutPiece::BoundingRect(piece.m_externalContourPoints)
|
||||
.adjusted(-data.m_pieceGap, -data.m_pieceGap, data.m_pieceGap, data.m_pieceGap);
|
||||
QVector<QPointF> const path1 = VPPiece::PrepareStickyPath(piece.m_externalContourPoints);
|
||||
bool hasInvalidPieceGapPosition = false;
|
||||
VSheetPiece invalidPiece;
|
||||
|
||||
for (const auto &p : data.m_pieces)
|
||||
{
|
||||
if (piece.m_id == p.m_id)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QRectF const path2Rect =
|
||||
VLayoutPiece::BoundingRect(p.m_externalContourPoints)
|
||||
.adjusted(-data.m_pieceGap, -data.m_pieceGap, data.m_pieceGap, data.m_pieceGap);
|
||||
|
||||
if (!path1Rect.intersects(path2Rect) && !path1Rect.contains(path2Rect) && !path2Rect.contains(path1Rect))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QVector<QPointF> const path2 = VPPiece::PrepareStickyPath(p.m_externalContourPoints);
|
||||
|
||||
QLineF const distance = VPPiece::ClosestDistance(path1, path2);
|
||||
|
||||
if (distance.length() < data.m_pieceGap - accuracyPointOnLine)
|
||||
{
|
||||
hasInvalidPieceGapPosition = true;
|
||||
invalidPiece = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
auto UpdateValidity = [&validations, hasInvalidPieceGapPosition, &invalidPieces](const QString &id)
|
||||
{
|
||||
VPiecePositionValidity validation = validations.value(id);
|
||||
validation.m_gap = hasInvalidPieceGapPosition;
|
||||
validations.insert(id, validation);
|
||||
if (hasInvalidPieceGapPosition)
|
||||
{
|
||||
invalidPieces.insert(id);
|
||||
}
|
||||
};
|
||||
|
||||
UpdateValidity(piece.m_id);
|
||||
|
||||
if (!invalidPiece.m_id.isEmpty())
|
||||
{
|
||||
UpdateValidity(invalidPiece.m_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto ValidatePiecesPositions(const VPiecesValidationData &data) -> QHash<QString, VPiecePositionValidity>
|
||||
{
|
||||
QHash<QString, VPiecePositionValidity> validations;
|
||||
|
||||
if (data.m_warnPiecesOutOfBound)
|
||||
{
|
||||
ValidatePiecesOutOfBound(data, validations);
|
||||
}
|
||||
|
||||
if (data.m_warnSuperpositionOfPieces)
|
||||
{
|
||||
ValidateSuperpositionOfPieces(data, validations);
|
||||
}
|
||||
|
||||
if (data.m_warnPieceGapePosition)
|
||||
{
|
||||
ValidatePiecesGapePosition(data, validations);
|
||||
}
|
||||
|
||||
return validations;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// VPSheetSceneData
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VPSheetSceneData::VPSheetSceneData(const VPLayoutPtr &layout, const QUuid &sheetUuid)
|
||||
|
@ -339,7 +538,8 @@ void VPSheetSceneData::ConnectPiece(VPGraphicsPiece *piece) const
|
|||
VPSheet::VPSheet(const VPLayoutPtr &layout, QObject *parent)
|
||||
: QObject(parent),
|
||||
m_layout(layout),
|
||||
m_sceneData(QSharedPointer<VPSheetSceneData>::create(layout, Uuid()))
|
||||
m_sceneData(QSharedPointer<VPSheetSceneData>::create(layout, Uuid())),
|
||||
m_validityWatcher(new QFutureWatcher<QHash<QString, VPiecePositionValidity>>(this))
|
||||
{
|
||||
SCASSERT(not layout.isNull())
|
||||
|
||||
|
@ -347,10 +547,16 @@ VPSheet::VPSheet(const VPLayoutPtr &layout, QObject *parent)
|
|||
SetIgnoreMargins(settings->GetLayoutSheetIgnoreMargins());
|
||||
SetSheetMargins(settings->GetLayoutSheetMargins());
|
||||
SetSheetSize(QSizeF(settings->GetLayoutSheetPaperWidth(), settings->GetLayoutSheetPaperHeight()));
|
||||
|
||||
connect(m_validityWatcher, &QFutureWatcher<QHash<QString, VPiecePositionValidity>>::finished, this,
|
||||
&VPSheet::UpdatePiecesValidity);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VPSheet::~VPSheet() = default;
|
||||
VPSheet::~VPSheet()
|
||||
{
|
||||
m_validityWatcher->cancel();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPSheet::GetLayout() const -> VPLayoutPtr
|
||||
|
@ -508,171 +714,6 @@ void VPSheet::SetTrashSheet(bool newTrashSheet)
|
|||
m_trashSheet = newTrashSheet;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::ValidateSuperpositionOfPieces() const
|
||||
{
|
||||
QList<VPPiecePtr> const pieces = GetPieces();
|
||||
|
||||
for (const auto &piece : pieces)
|
||||
{
|
||||
if (piece.isNull() || piece->OutOfBound())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool oldSuperpositionOfPieces = piece->HasSuperpositionWithPieces();
|
||||
QVector<QPointF> path1;
|
||||
CastTo(piece->GetMappedExternalContourPoints(), path1);
|
||||
bool hasSuperposition = false;
|
||||
|
||||
for (const auto &p : pieces)
|
||||
{
|
||||
if (p.isNull() || piece == p)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QVector<QPointF> path2;
|
||||
CastTo(p->GetMappedExternalContourPoints(), path2);
|
||||
|
||||
bool const superposition = VPPiece::PathsSuperposition(path1, path2);
|
||||
if (superposition)
|
||||
{
|
||||
hasSuperposition = superposition;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
piece->SetHasSuperpositionWithPieces(hasSuperposition);
|
||||
|
||||
if (oldSuperpositionOfPieces != piece->HasSuperpositionWithPieces())
|
||||
{
|
||||
VPLayoutPtr const layout = GetLayout();
|
||||
if (not layout.isNull())
|
||||
{
|
||||
emit layout->PiecePositionValidityChanged(piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::ValidatePieceGapePosition(const VPPiecePtr &piece) const
|
||||
{
|
||||
VPLayoutPtr const layout = GetLayout();
|
||||
if (layout.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const qreal pieceGap = layout->LayoutSettings().GetPiecesGap();
|
||||
if (pieceGap <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (piece.isNull() || piece->HasSuperpositionWithPieces() || piece->OutOfBound())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool oldInvalidPieceGapPosition = piece->HasInvalidPieceGapPosition();
|
||||
|
||||
QVector<QPointF> path1;
|
||||
CastTo(piece->GetMappedExternalContourPoints(), path1);
|
||||
path1 = VPPiece::PrepareStickyPath(path1);
|
||||
bool hasInvalidPieceGapPosition = false;
|
||||
|
||||
QList<VPPiecePtr> const pieces = GetPieces();
|
||||
|
||||
for (const auto &p : pieces)
|
||||
{
|
||||
if (p.isNull() || piece == p)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QVector<QPointF> path2;
|
||||
CastTo(p->GetMappedExternalContourPoints(), path2);
|
||||
path2 = VPPiece::PrepareStickyPath(path2);
|
||||
|
||||
QLineF const distance = VPPiece::ClosestDistance(path1, path2);
|
||||
|
||||
if (distance.length() < pieceGap - accuracyPointOnLine)
|
||||
{
|
||||
hasInvalidPieceGapPosition = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
piece->SetHasInvalidPieceGapPosition(hasInvalidPieceGapPosition);
|
||||
|
||||
if (oldInvalidPieceGapPosition != piece->HasInvalidPieceGapPosition())
|
||||
{
|
||||
VPLayoutPtr const layout = GetLayout();
|
||||
if (not layout.isNull())
|
||||
{
|
||||
emit layout->PiecePositionValidityChanged(piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::ValidatePieceGapePosition() const
|
||||
{
|
||||
QList<VPPiecePtr> const pieces = GetPieces();
|
||||
for (const auto &piece : pieces)
|
||||
{
|
||||
ValidatePieceGapePosition(piece);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::ValidatePieceOutOfBound(const VPPiecePtr &piece) const
|
||||
{
|
||||
if (piece.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool oldOutOfBound = piece->OutOfBound();
|
||||
QRectF const sheetRect = GetMarginsRect();
|
||||
|
||||
VPLayoutPtr const layout = GetLayout();
|
||||
if (not layout.isNull() && layout->LayoutSettings().IsCutOnFold() && not piece->IsShowFullPiece() &&
|
||||
!piece->GetSeamMirrorLine().isNull())
|
||||
{
|
||||
QLineF const foldLine = sheetRect.width() >= sheetRect.height()
|
||||
? QLineF(sheetRect.topLeft(), sheetRect.topRight())
|
||||
: QLineF(sheetRect.topRight(), sheetRect.bottomRight());
|
||||
piece->SetOutOfBound(not VGObject::IsLineSegmentOnLineSegment(
|
||||
foldLine, piece->GetMappedSeamAllowanceMirrorLine(), MmToPixel(0.5)));
|
||||
}
|
||||
else
|
||||
{
|
||||
QRectF const pieceRect = piece->MappedDetailBoundingRect();
|
||||
piece->SetOutOfBound(not sheetRect.contains(pieceRect));
|
||||
}
|
||||
|
||||
if (oldOutOfBound != piece->OutOfBound())
|
||||
{
|
||||
if (not layout.isNull())
|
||||
{
|
||||
emit layout->PiecePositionValidityChanged(piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::ValidatePiecesOutOfBound() const
|
||||
{
|
||||
QList<VPPiecePtr> const pieces = GetPieces();
|
||||
for (const auto &piece : pieces)
|
||||
{
|
||||
ValidatePieceOutOfBound(piece);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPSheet::GetSheetRect() const -> QRectF
|
||||
{
|
||||
|
@ -752,32 +793,91 @@ void VPSheet::RemoveUnusedLength()
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::CheckPiecePositionValidity(const VPPiecePtr &piece) const
|
||||
void VPSheet::CheckPiecesPositionValidity() const
|
||||
{
|
||||
if (m_validityWatcher->isFinished())
|
||||
{
|
||||
VPLayoutPtr const layout = GetLayout();
|
||||
if (layout.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
VPiecesValidationData data;
|
||||
data.m_warnPiecesOutOfBound = layout->LayoutSettings().GetWarningPiecesOutOfBound();
|
||||
data.m_warnSuperpositionOfPieces = layout->LayoutSettings().GetWarningSuperpositionOfPieces();
|
||||
data.m_warnPieceGapePosition = layout->LayoutSettings().GetWarningPieceGapePosition();
|
||||
data.m_cutOnFold = layout->LayoutSettings().IsCutOnFold();
|
||||
data.m_sheetRect = GetMarginsRect();
|
||||
data.m_pieceGap = layout->LayoutSettings().GetPiecesGap();
|
||||
|
||||
QList<VPPiecePtr> const pieces = GetPieces();
|
||||
QVector<VSheetPiece> sheetPieces;
|
||||
sheetPieces.reserve(pieces.size());
|
||||
|
||||
for (const auto &piece : pieces)
|
||||
{
|
||||
VSheetPiece data;
|
||||
data.m_showFullPiece = piece->IsShowFullPiece();
|
||||
data.m_id = piece->GetUniqueID();
|
||||
data.m_seamMirrorLine = piece->GetMappedSeamMirrorLine();
|
||||
data.m_seamAllowanceMirrorLine = piece->GetMappedSeamAllowanceMirrorLine();
|
||||
|
||||
QVector<QPointF> points;
|
||||
CastTo(piece->GetMappedExternalContourPoints(), points);
|
||||
data.m_externalContourPoints = points;
|
||||
|
||||
sheetPieces.append(data);
|
||||
}
|
||||
|
||||
data.m_pieces = sheetPieces;
|
||||
|
||||
m_validationStale = false;
|
||||
m_validityWatcher->setFuture(QtConcurrent::run([data]() { return ValidatePiecesPositions(data); }));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_validationStale = true;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPSheet::UpdatePiecesValidity()
|
||||
{
|
||||
QHash<QString, VPiecePositionValidity> const newValidations = m_validityWatcher->future().result();
|
||||
|
||||
QList<VPPiecePtr> const pieces = GetPieces();
|
||||
QHash<QString, VPPiecePtr> sortedPieces;
|
||||
sortedPieces.reserve(pieces.size());
|
||||
|
||||
for (const auto &piece : pieces)
|
||||
{
|
||||
sortedPieces.insert(piece->GetUniqueID(), piece);
|
||||
}
|
||||
|
||||
VPLayoutPtr const layout = GetLayout();
|
||||
if (layout.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (QList<VPPiecePtr> const pieces = GetPieces(); piece.isNull() || not pieces.contains(piece))
|
||||
for (auto i = newValidations.cbegin(), end = newValidations.cend(); i != end; ++i)
|
||||
{
|
||||
return;
|
||||
if (sortedPieces.contains(i.key()))
|
||||
{
|
||||
VPPiecePtr const piece = sortedPieces.value(i.key());
|
||||
piece->SetOutOfBound(i.value().m_outOfBound);
|
||||
piece->SetHasSuperpositionWithPieces(i.value().m_superposition);
|
||||
piece->SetHasInvalidPieceGapPosition(i.value().m_gap);
|
||||
|
||||
emit layout->PiecePositionValidityChanged(piece);
|
||||
}
|
||||
}
|
||||
|
||||
if (layout->LayoutSettings().GetWarningPiecesOutOfBound())
|
||||
if (m_validationStale)
|
||||
{
|
||||
ValidatePieceOutOfBound(piece);
|
||||
}
|
||||
|
||||
if (layout->LayoutSettings().GetWarningSuperpositionOfPieces())
|
||||
{
|
||||
ValidateSuperpositionOfPieces();
|
||||
}
|
||||
|
||||
if (layout->LayoutSettings().GetWarningPieceGapePosition())
|
||||
{
|
||||
ValidatePieceGapePosition(piece);
|
||||
m_validationStale = false;
|
||||
CheckPiecesPositionValidity();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#define VPSHEET_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QFutureWatcher>
|
||||
#include <QList>
|
||||
#include <QMarginsF>
|
||||
#include <QPageLayout>
|
||||
|
@ -50,6 +51,13 @@ class VPGraphicsSheet;
|
|||
class VLayoutPiece;
|
||||
class QGraphicsItem;
|
||||
|
||||
struct VPiecePositionValidity
|
||||
{
|
||||
bool m_outOfBound{false};
|
||||
bool m_superposition{false};
|
||||
bool m_gap{false};
|
||||
};
|
||||
|
||||
class VPSheetSceneData
|
||||
{
|
||||
public:
|
||||
|
@ -183,12 +191,6 @@ public:
|
|||
auto TrashSheet() const -> bool;
|
||||
void SetTrashSheet(bool newTrashSheet);
|
||||
|
||||
void ValidateSuperpositionOfPieces() const;
|
||||
void ValidatePieceGapePosition(const VPPiecePtr &piece) const;
|
||||
void ValidatePieceGapePosition() const;
|
||||
void ValidatePieceOutOfBound(const VPPiecePtr &piece) const;
|
||||
void ValidatePiecesOutOfBound() const;
|
||||
|
||||
auto GetSheetRect() const -> QRectF;
|
||||
auto GetMarginsRect() const -> QRectF;
|
||||
|
||||
|
@ -283,7 +285,10 @@ public:
|
|||
auto GetSheetOrientation() const -> QPageLayout::Orientation;
|
||||
|
||||
public slots:
|
||||
void CheckPiecePositionValidity(const VPPiecePtr &piece) const;
|
||||
void CheckPiecesPositionValidity() const;
|
||||
|
||||
private slots:
|
||||
void UpdatePiecesValidity();
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY_MOVE(VPSheet) // NOLINT
|
||||
|
@ -316,6 +321,9 @@ private:
|
|||
|
||||
QSharedPointer<VPSheetSceneData> m_sceneData{nullptr};
|
||||
|
||||
QFutureWatcher<QHash<QString, VPiecePositionValidity>> *m_validityWatcher;
|
||||
mutable bool m_validationStale{false};
|
||||
|
||||
auto SheetUnits() const -> Unit;
|
||||
};
|
||||
|
||||
|
|
|
@ -650,9 +650,7 @@ void VPMainGraphicsView::RemovePiece() const
|
|||
if (not layout.isNull())
|
||||
{
|
||||
emit layout->PieceSelectionChanged(piece);
|
||||
|
||||
auto *command = new VPUndoMovePieceOnSheet(VPSheetPtr(), piece);
|
||||
layout->UndoStack()->push(command);
|
||||
layout->UndoStack()->push(new VPUndoMovePieceOnSheet(VPSheetPtr(), piece));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1119,7 +1119,7 @@ void VPMainWindow::InitMarginsData(const QString &suffix)
|
|||
LayoutWasSaved(false);
|
||||
m_layout->TileFactory()->RefreshTileInfos();
|
||||
m_graphicsView->RefreshLayout();
|
||||
m_layout->CheckPiecesPositionValidity(sheet);
|
||||
sheet->CheckPiecesPositionValidity();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -2140,7 +2140,10 @@ void VPMainWindow::SheetPaperSizeChanged()
|
|||
}
|
||||
else
|
||||
{
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull())
|
||||
{
|
||||
sheet->CheckPiecesPositionValidity();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3908,7 +3911,7 @@ void VPMainWindow::on_SheetMarginChanged()
|
|||
|
||||
LayoutWasSaved(false);
|
||||
|
||||
m_layout->CheckPiecesPositionValidity(sheet);
|
||||
sheet->CheckPiecesPositionValidity();
|
||||
}
|
||||
|
||||
m_graphicsView->RefreshLayout();
|
||||
|
@ -4910,7 +4913,10 @@ void VPMainWindow::LayoutWarningPieceGapePosition_toggled(bool checked)
|
|||
LayoutWasSaved(false);
|
||||
if (checked)
|
||||
{
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull())
|
||||
{
|
||||
sheet->CheckPiecesPositionValidity();
|
||||
}
|
||||
}
|
||||
m_graphicsView->RefreshPieces();
|
||||
}
|
||||
|
@ -4925,7 +4931,11 @@ void VPMainWindow::LayoutWarningPiecesSuperposition_toggled(bool checked)
|
|||
LayoutWasSaved(false);
|
||||
if (checked)
|
||||
{
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
|
||||
if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull())
|
||||
{
|
||||
sheet->CheckPiecesPositionValidity();
|
||||
}
|
||||
}
|
||||
m_graphicsView->RefreshPieces();
|
||||
}
|
||||
|
@ -4941,7 +4951,10 @@ void VPMainWindow::LayoutWarningPiecesOutOfBound_toggled(bool checked)
|
|||
|
||||
if (checked)
|
||||
{
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull())
|
||||
{
|
||||
sheet->CheckPiecesPositionValidity();
|
||||
}
|
||||
}
|
||||
m_graphicsView->RefreshPieces();
|
||||
}
|
||||
|
@ -4954,7 +4967,10 @@ void VPMainWindow::LayoutCutOnFold_toggled(bool checked)
|
|||
{
|
||||
m_layout->LayoutSettings().SetCutOnFold(checked);
|
||||
LayoutWasSaved(false);
|
||||
m_layout->CheckPiecesPositionValidity(m_layout->GetFocusedSheet());
|
||||
if (VPSheetPtr sheet = m_layout->GetFocusedSheet(); !sheet.isNull())
|
||||
{
|
||||
sheet->CheckPiecesPositionValidity();
|
||||
}
|
||||
m_graphicsView->RefreshLayout();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user