Warnings piece out of bound and superposition of pieces.

This commit is contained in:
Roman Telezhynskyi 2021-08-27 18:27:38 +03:00
parent 877fe380e3
commit 5c9b71dee4
14 changed files with 387 additions and 74 deletions

View File

@ -147,6 +147,7 @@ auto VPLayout::AddSheet(const VPSheetPtr &sheet) -> VPSheetPtr
if (not sheet.isNull() && GetSheet(sheet->Uuid()).isNull()) if (not sheet.isNull() && GetSheet(sheet->Uuid()).isNull())
{ {
m_sheets.append(sheet); m_sheets.append(sheet);
connect(this, &VPLayout::PieceTransformationChanged, sheet.get(), &VPSheet::CheckPiecePositionValidity);
} }
return sheet; return sheet;
} }
@ -269,6 +270,19 @@ void VPLayout::Clear()
m_layoutSettings = VPLayoutSettings(); m_layoutSettings = VPLayoutSettings();
} }
//---------------------------------------------------------------------------------------------------------------------
void VPLayout::CheckPiecesPositionValidity() const
{
for (const auto &sheet : m_sheets)
{
if (not sheet.isNull())
{
sheet->ValidateSuperpositionOfPieces();
sheet->ValidatePiecesOutOfBound();
}
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPLayout::AddTrashSheet(const VPSheetPtr &sheet) void VPLayout::AddTrashSheet(const VPSheetPtr &sheet)
{ {

View File

@ -85,6 +85,8 @@ public:
void Clear(); void Clear();
void CheckPiecesPositionValidity() const;
signals: signals:
void PieceSheetChanged(const VPPiecePtr &piece); void PieceSheetChanged(const VPPiecePtr &piece);
void ActiveSheetChanged(const VPSheetPtr &focusedSheet); void ActiveSheetChanged(const VPSheetPtr &focusedSheet);
@ -92,6 +94,7 @@ signals:
void TransformationOriginChanged(); void TransformationOriginChanged();
void SheetListChanged(); void SheetListChanged();
void PieceSelectionChanged(const VPPiecePtr &piece); void PieceSelectionChanged(const VPPiecePtr &piece);
void PiecePositionValidityChanged(const VPPiecePtr &piece);
void LayoutChanged(); void LayoutChanged();
protected: protected:

View File

@ -152,43 +152,6 @@ void VPPiece::RotateToGrainline(const VPTransformationOrigon &origin)
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetSelected(bool value)
{
m_isSelected = value;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::IsSelected() const -> bool
{
return m_isSelected;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::Sheet() const -> VPSheetPtr
{
return m_sheet;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetSheet(const VPSheetPtr &newSheet)
{
m_sheet = newSheet;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPPiece::Layout() const -> VPLayoutPtr
{
return m_layout;
}
//---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetLayout(const VPLayoutPtr &layout)
{
SCASSERT(layout != nullptr)
m_layout = layout;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPPiece::SetGrainlineEnabled(bool enabled) void VPPiece::SetGrainlineEnabled(bool enabled)
{ {

View File

@ -106,6 +106,12 @@ public:
*/ */
void Flip(); void Flip();
auto OutOfBound() const -> bool;
void SetOutOfBound(bool newOutOfBound);
auto HasSuperpositionWithPieces() const -> bool;
void SetHasSuperpositionWithPieces(bool newHasSuperpositionWithPieces);
private: private:
Q_DISABLE_COPY(VPPiece) Q_DISABLE_COPY(VPPiece)
@ -114,8 +120,71 @@ private:
VPSheetWeakPtr m_sheet{}; VPSheetWeakPtr m_sheet{};
bool m_isSelected{false}; bool m_isSelected{false};
bool m_outOfBound{false};
bool m_hasSuperpositionWithPieces{false};
}; };
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetSelected(bool value)
{
m_isSelected = value;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::IsSelected() const -> bool
{
return m_isSelected;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::Sheet() const -> VPSheetPtr
{
return m_sheet;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetSheet(const VPSheetPtr &newSheet)
{
m_sheet = newSheet;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::Layout() const -> VPLayoutPtr
{
return m_layout;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetLayout(const VPLayoutPtr &layout)
{
SCASSERT(layout != nullptr)
m_layout = layout;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::OutOfBound() const -> bool
{
return m_outOfBound;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetOutOfBound(bool newOutOfBound)
{
m_outOfBound = newOutOfBound;
}
//---------------------------------------------------------------------------------------------------------------------
inline auto VPPiece::HasSuperpositionWithPieces() const -> bool
{
return m_hasSuperpositionWithPieces;
}
//---------------------------------------------------------------------------------------------------------------------
inline void VPPiece::SetHasSuperpositionWithPieces(bool newHasSuperpositionWithPieces)
{
m_hasSuperpositionWithPieces = newHasSuperpositionWithPieces;
}
Q_DECLARE_METATYPE(VPPiecePtr) Q_DECLARE_METATYPE(VPPiecePtr)
#endif // VPPIECE_H #endif // VPPIECE_H

View File

@ -158,3 +158,178 @@ void VPSheet::SetTrashSheet(bool newTrashSheet)
{ {
m_trashSheet = newTrashSheet; m_trashSheet = newTrashSheet;
} }
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::ValidateSuperpositionOfPieces() const
{
QList<VPPiecePtr> pieces = GetPieces();
for (const auto &piece : pieces)
{
if (piece.isNull())
{
continue;
}
const bool oldSuperpositionOfPieces = piece->HasSuperpositionWithPieces();
QVector<QPointF> path1 = piece->GetMappedExternalContourPoints();
bool hasSuperposition = false;
for (const auto &p : pieces)
{
if (p.isNull() || piece == p)
{
continue;
}
QVector<QPointF> path2 = p->GetMappedExternalContourPoints();
bool superposition = PathsSuperposition(path1, path2);
if (superposition)
{
hasSuperposition = superposition;
break;
}
}
piece->SetHasSuperpositionWithPieces(hasSuperposition);
if (oldSuperpositionOfPieces != piece->HasSuperpositionWithPieces())
{
VPLayoutPtr layout = GetLayout();
if (not layout.isNull())
{
emit layout->PiecePositionValidityChanged(piece);
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::ValidatePieceOutOfBound(const VPPiecePtr &piece) const
{
if (piece.isNull())
{
return;
}
const bool oldOutOfBound = piece->OutOfBound();
QRectF pieceRect = piece->MappedDetailBoundingRect();
QRectF sheetRect = GetMarginsRect();
piece->SetOutOfBound(not sheetRect.contains(pieceRect));
if (oldOutOfBound != piece->OutOfBound())
{
VPLayoutPtr layout = GetLayout();
if (not layout.isNull())
{
emit layout->PiecePositionValidityChanged(piece);
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::ValidatePiecesOutOfBound() const
{
QList<VPPiecePtr> pieces = GetPieces();
for (const auto &piece : pieces)
{
ValidatePieceOutOfBound(piece);
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetSheetRect() const -> QRectF
{
return GetSheetRect(GetLayout());
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetMarginsRect() const -> QRectF
{
return GetMarginsRect(GetLayout());
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetSheetRect(const VPLayoutPtr &layout) -> QRectF
{
if (layout.isNull())
{
return {};
}
QPoint topLeft = QPoint(0,0);
QSizeF size = layout->LayoutSettings().GetSheetSize();
QRectF rect = QRectF(topLeft, size);
return rect;
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::GetMarginsRect(const VPLayoutPtr &layout) -> QRectF
{
if (layout.isNull())
{
return {};
}
QSizeF size = layout->LayoutSettings().GetSheetSize();
if (not layout->LayoutSettings().IgnoreMargins())
{
QMarginsF margins = layout->LayoutSettings().GetSheetMargins();
QRectF rect = QRectF(QPointF(margins.left(), margins.top()),
QPointF(size.width()-margins.right(), size.height()-margins.bottom()));
return rect;
}
return QRectF(0, 0, size.width(), size.height());
}
//---------------------------------------------------------------------------------------------------------------------
void VPSheet::CheckPiecePositionValidity(const VPPiecePtr &piece) const
{
VPLayoutPtr layout = GetLayout();
if (layout.isNull())
{
return;
}
QList<VPPiecePtr> pieces = GetPieces();
if (piece.isNull() || not pieces.contains(piece))
{
return;
}
if (layout->LayoutSettings().GetWarningPiecesOutOfBound())
{
ValidatePieceOutOfBound(piece);
}
if (layout->LayoutSettings().GetWarningSuperpositionOfPieces())
{
ValidateSuperpositionOfPieces();
}
}
//---------------------------------------------------------------------------------------------------------------------
auto VPSheet::PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) const -> bool
{
const QRectF path1Rect = VLayoutPiece::BoundingRect(path1);
const QPainterPath path1Path = VAbstractPiece::PainterPath(path1);
const QRectF path2Rect = VLayoutPiece::BoundingRect(path2);
const QPainterPath path2Path = VAbstractPiece::PainterPath(path2);
if (path1Rect.intersects(path2Rect) || path2Rect.contains(path1Rect) || path1Rect.contains(path2Rect))
{
if (path1Path.contains(path2Path) || path2Path.contains(path1Path) || path1Path.intersects(path2Path))
{
return true;
}
}
return false;
}

View File

@ -40,8 +40,9 @@
class VPLayout; class VPLayout;
class VPPiece; class VPPiece;
class VPSheet class VPSheet : public QObject
{ {
Q_OBJECT
public: public:
explicit VPSheet(const VPLayoutPtr &layout); explicit VPSheet(const VPLayoutPtr &layout);
@ -84,6 +85,19 @@ public:
auto TrashSheet() const -> bool; auto TrashSheet() const -> bool;
void SetTrashSheet(bool newTrashSheet); void SetTrashSheet(bool newTrashSheet);
void ValidateSuperpositionOfPieces() const;
void ValidatePieceOutOfBound(const VPPiecePtr &piece) const;
void ValidatePiecesOutOfBound() const;
auto GetSheetRect() const -> QRectF;
auto GetMarginsRect() const -> QRectF;
static auto GetSheetRect(const VPLayoutPtr &layout) -> QRectF;
static auto GetMarginsRect(const VPLayoutPtr &layout) -> QRectF;
public slots:
void CheckPiecePositionValidity(const VPPiecePtr &piece) const;
private: private:
Q_DISABLE_COPY(VPSheet) Q_DISABLE_COPY(VPSheet)
@ -97,6 +111,8 @@ private:
bool m_trashSheet{false}; bool m_trashSheet{false};
VPTransformationOrigon m_transformationOrigin{}; VPTransformationOrigon m_transformationOrigin{};
auto PathsSuperposition(const QVector<QPointF> &path1, const QVector<QPointF> &path2) const -> bool;
}; };
Q_DECLARE_METATYPE(VPSheetPtr) Q_DECLARE_METATYPE(VPSheetPtr)

View File

@ -55,6 +55,9 @@ Q_LOGGING_CATEGORY(pGraphicsPiece, "p.graphicsPiece")
namespace namespace
{ {
constexpr qreal penWidth = 1; constexpr qreal penWidth = 1;
QColor mainColor = Qt::black;
QColor errorColor = Qt::red;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -112,7 +115,7 @@ void VPGraphicsPiece::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
Q_UNUSED(widget); Q_UNUSED(widget);
Q_UNUSED(option); Q_UNUSED(option);
QPen pen(Qt::black, penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); QPen pen(PieceColor(), penWidth, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin);
painter->setPen(pen); painter->setPen(pen);
PaintPiece(painter); PaintPiece(painter);
@ -407,6 +410,41 @@ void VPGraphicsPiece::GroupMove(const QPointF &pos)
} }
} }
//---------------------------------------------------------------------------------------------------------------------
QColor VPGraphicsPiece::PieceColor() const
{
VPPiecePtr piece = m_piece.toStrongRef();
if (piece.isNull())
{
return mainColor;
}
VPLayoutPtr layout = piece->Layout();
if (layout.isNull())
{
return mainColor;
}
bool outOfBound = false;
if (layout->LayoutSettings().GetWarningPiecesOutOfBound())
{
outOfBound = piece->OutOfBound();
}
bool superposition = false;
if (layout->LayoutSettings().GetWarningSuperpositionOfPieces())
{
superposition = piece->HasSuperpositionWithPieces();
}
if (outOfBound || superposition)
{
return errorColor;
}
return mainColor;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPGraphicsPiece::on_RefreshPiece(const VPPiecePtr &piece) void VPGraphicsPiece::on_RefreshPiece(const VPPiecePtr &piece)
{ {

View File

@ -92,6 +92,8 @@ private:
void PaintPiece(QPainter *painter=nullptr); void PaintPiece(QPainter *painter=nullptr);
void GroupMove(const QPointF &pos); void GroupMove(const QPointF &pos);
QColor PieceColor() const;
}; };
#endif // VPGRAPHICSPIECE_H #endif // VPGRAPHICSPIECE_H

View File

@ -105,38 +105,13 @@ void VPGraphicsSheet::paint(QPainter *painter, const QStyleOptionGraphicsItem *o
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::GetSheetRect() const -> QRectF auto VPGraphicsSheet::GetSheetRect() const -> QRectF
{ {
VPLayoutPtr layout = m_layout.toStrongRef(); return VPSheet::GetSheetRect(m_layout.toStrongRef());
if (layout.isNull())
{
return {};
}
QPoint topLeft = QPoint(0,0);
QSizeF size = layout->LayoutSettings().GetSheetSize();
QRectF rect = QRectF(topLeft, size);
return rect;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
auto VPGraphicsSheet::GetMarginsRect() const -> QRectF auto VPGraphicsSheet::GetMarginsRect() const -> QRectF
{ {
VPLayoutPtr layout = m_layout.toStrongRef(); return VPSheet::GetMarginsRect(m_layout.toStrongRef());
if (layout.isNull())
{
return {};
}
QSizeF size = layout->LayoutSettings().GetSheetSize();
if (not layout->LayoutSettings().IgnoreMargins())
{
QMarginsF margins = layout->LayoutSettings().GetSheetMargins();
QRectF rect = QRectF(QPointF(margins.left(), margins.top()),
QPointF(size.width()-margins.right(), size.height()-margins.bottom()));
return rect;
}
return QRectF(0, 0, size.width(), size.height());
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -515,6 +515,8 @@ void VPMainGraphicsView::ConnectPiece(VPGraphicsPiece *piece)
&VPGraphicsPiece::on_RefreshPiece); &VPGraphicsPiece::on_RefreshPiece);
connect(layout.get(), &VPLayout::PieceSelectionChanged, connect(layout.get(), &VPLayout::PieceSelectionChanged,
m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls);
connect(layout.get(), &VPLayout::PiecePositionValidityChanged,
piece, &VPGraphicsPiece::on_RefreshPiece);
connect(piece, &VPGraphicsPiece::PieceTransformationChanged, connect(piece, &VPGraphicsPiece::PieceTransformationChanged,
m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls); m_rotationControls, &VPGraphicsPieceControls::on_UpdateControls);
connect(piece, &VPGraphicsPiece::HideTransformationHandles, connect(piece, &VPGraphicsPiece::HideTransformationHandles,

View File

@ -122,6 +122,7 @@ void VPUndoMovePieceOnSheet::redo()
if (not layout.isNull()) if (not layout.isNull())
{ {
emit layout->PieceSheetChanged(piece); emit layout->PieceSheetChanged(piece);
emit layout->PieceTransformationChanged(piece);
} }
} }
} }

View File

@ -284,6 +284,7 @@ auto VPMainWindow::LoadFile(QString path) -> bool
m_graphicsView->RefreshLayout(); m_graphicsView->RefreshLayout();
m_graphicsView->RefreshPieces(); m_graphicsView->RefreshPieces();
m_tileFactory->refreshTileInfos(); m_tileFactory->refreshTileInfos();
m_layout->CheckPiecesPositionValidity();
VMainGraphicsView::NewSceneRect(m_graphicsView->scene(), m_graphicsView); VMainGraphicsView::NewSceneRect(m_graphicsView->scene(), m_graphicsView);
return true; return true;
@ -732,6 +733,12 @@ void VPMainWindow::InitPropertyTabCurrentSheet()
LayoutWasSaved(false); LayoutWasSaved(false);
m_tileFactory->refreshTileInfos(); m_tileFactory->refreshTileInfos();
m_graphicsView->RefreshLayout(); m_graphicsView->RefreshLayout();
VPSheetPtr sheet = m_layout->GetFocusedSheet();
if (not sheet.isNull())
{
sheet->ValidatePiecesOutOfBound();
}
} }
}); });
@ -834,7 +841,15 @@ void VPMainWindow::InitPropertyTabLayout()
{ {
m_layout->LayoutSettings().SetWarningSuperpositionOfPieces(checked); m_layout->LayoutSettings().SetWarningSuperpositionOfPieces(checked);
LayoutWasSaved(false); LayoutWasSaved(false);
// TODO update the QGraphicView if (checked)
{
VPSheetPtr sheet = m_layout->GetFocusedSheet();
if (not sheet.isNull())
{
sheet->ValidateSuperpositionOfPieces();
}
}
m_graphicsView->RefreshPieces();
} }
}); });
@ -844,7 +859,16 @@ void VPMainWindow::InitPropertyTabLayout()
{ {
m_layout->LayoutSettings().SetWarningPiecesOutOfBound(checked); m_layout->LayoutSettings().SetWarningPiecesOutOfBound(checked);
LayoutWasSaved(false); LayoutWasSaved(false);
// TODO update the QGraphicView
if (checked)
{
VPSheetPtr sheet = m_layout->GetFocusedSheet();
if (not sheet.isNull())
{
sheet->ValidatePiecesOutOfBound();
}
}
m_graphicsView->RefreshPieces();
} }
}); });
@ -1748,9 +1772,18 @@ void VPMainWindow::SheetPaperSizeChanged()
ui->toolButtonSheetLandscapeOrientation->setChecked(not portrait); ui->toolButtonSheetLandscapeOrientation->setChecked(not portrait);
ui->toolButtonSheetLandscapeOrientation->blockSignals(false); ui->toolButtonSheetLandscapeOrientation->blockSignals(false);
if (not m_layout.isNull() && m_layout->LayoutSettings().GetFollowGrainline()) if (not m_layout.isNull())
{ {
RotatePiecesToGrainline(); if (m_layout->LayoutSettings().GetFollowGrainline())
{
RotatePiecesToGrainline();
}
VPSheetPtr sheet = m_layout->GetFocusedSheet();
if (not sheet.isNull())
{
sheet->ValidatePiecesOutOfBound();
}
} }
} }
@ -2224,6 +2257,13 @@ void VPMainWindow::on_SheetMarginChanged()
ui->doubleSpinBoxSheetMarginBottom->value()); ui->doubleSpinBoxSheetMarginBottom->value());
LayoutWasSaved(false); LayoutWasSaved(false);
VPSheetPtr sheet = m_layout->GetFocusedSheet();
if (not sheet.isNull())
{
sheet->ValidatePiecesOutOfBound();
}
m_graphicsView->RefreshLayout(); m_graphicsView->RefreshLayout();
} }
} }

View File

@ -1048,15 +1048,13 @@ int VLayoutPiece::LayoutEdgeByPoint(const QPointF &p1) const
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QRectF VLayoutPiece::MappedDetailBoundingRect() const QRectF VLayoutPiece::MappedDetailBoundingRect() const
{ {
return IsSeamAllowance() && not IsSeamAllowanceBuiltIn() ? BoundingRect(GetMappedSeamAllowancePoints()) : return BoundingRect(GetMappedExternalContourPoints());
BoundingRect(GetMappedContourPoints());
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QRectF VLayoutPiece::DetailBoundingRect() const QRectF VLayoutPiece::DetailBoundingRect() const
{ {
return IsSeamAllowance() && not IsSeamAllowanceBuiltIn() ? BoundingRect(GetSeamAllowancePoints()) : return BoundingRect(GetExternalContourPoints());
BoundingRect(GetContourPoints());
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -1133,6 +1131,20 @@ void VLayoutPiece::SetLayoutAllowancePoints()
} }
} }
//---------------------------------------------------------------------------------------------------------------------
QVector<QPointF> VLayoutPiece::GetMappedExternalContourPoints() const
{
return IsSeamAllowance() && not IsSeamAllowanceBuiltIn() ? GetMappedSeamAllowancePoints() :
GetMappedContourPoints();
}
//---------------------------------------------------------------------------------------------------------------------
QVector<QPointF> VLayoutPiece::GetExternalContourPoints() const
{
return IsSeamAllowance() && not IsSeamAllowanceBuiltIn() ? GetSeamAllowancePoints() :
GetContourPoints();
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QVector<VLayoutPassmark> VLayoutPiece::GetMappedPassmarks() const QVector<VLayoutPassmark> VLayoutPiece::GetMappedPassmarks() const
{ {

View File

@ -86,6 +86,9 @@ public:
QVector<QPointF> GetLayoutAllowancePoints() const; QVector<QPointF> GetLayoutAllowancePoints() const;
void SetLayoutAllowancePoints(); void SetLayoutAllowancePoints();
QVector<QPointF> GetMappedExternalContourPoints() const;
QVector<QPointF> GetExternalContourPoints() const;
QVector<VLayoutPassmark> GetMappedPassmarks() const; QVector<VLayoutPassmark> GetMappedPassmarks() const;
QVector<VLayoutPassmark> GetPassmarks() const; QVector<VLayoutPassmark> GetPassmarks() const;
void SetPassmarks(const QVector<VLayoutPassmark> &passmarks); void SetPassmarks(const QVector<VLayoutPassmark> &passmarks);