Restore layout debug system.

This commit is contained in:
Roman Telezhynskyi 2020-11-26 19:10:09 +02:00
parent bccc852931
commit 4041f9e154
6 changed files with 276 additions and 3 deletions

View File

@ -293,6 +293,13 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
QCoreApplication::processEvents(); QCoreApplication::processEvents();
#ifdef LAYOUT_DEBUG
const QString path = QDir::homePath()+QStringLiteral("/LayoutDebug");
QDir debugDir(path);
debugDir.removeRecursively();
debugDir.mkpath(path);
#endif
forever forever
{ {
if (IsTimeout()) if (IsTimeout())
@ -307,7 +314,9 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
break; break;
} }
switch (lGenerator.State()) nestingState = lGenerator.State();
switch (nestingState)
{ {
case LayoutErrors::NoError: case LayoutErrors::NoError:
if (lGenerator.PapersCount() <= papersCount) if (lGenerator.PapersCount() <= papersCount)

View File

@ -115,4 +115,26 @@ struct VCachedPositions
QPainterPath layoutAllowancePath{}; QPainterPath layoutAllowancePath{};
}; };
/* Warning! Debugging doesn't work stable in debug mode. If you need big allocation use release mode. Or disable
* Address Sanitizer. See page https://bitbucket.org/dismine/valentina/wiki/developers/Address_Sanitizer
*/
//#define LAYOUT_DEBUG // Enable debug mode
// This block help rule debug mode. Don't turn all options at the same time!
#ifdef LAYOUT_DEBUG
// Nice looking
# define SHOW_VERTICES // Show contour vertices
# define SHOW_DIRECTION // Show contour direction
# define ARRANGED_DETAILS // Show already arranged details
# define SHOW_SHEET // Show sheet rect
# define SHOW_CANDIDATE // Show each position
// Debugging
//# define SHOW_ROTATION // For each position show rotation part
//# define SHOW_COMBINE // For each position show edge combine part
//# define SHOW_MIRROR // For each position show mirror part
//# define SHOW_CANDIDATE_BEST // For only correct positions that pass checks
# define SHOW_BEST // Show only best position for workpiece
#endif//LAYOUT_DEBUG
#endif // VLAYOUTDEF_H #endif // VLAYOUTDEF_H

View File

@ -43,6 +43,10 @@
#include <Qt> #include <Qt>
#include <QtAlgorithms> #include <QtAlgorithms>
#ifdef LAYOUT_DEBUG
#include <QMutex>
#endif
#include "vbestsquare.h" #include "vbestsquare.h"
#include "vcontour.h" #include "vcontour.h"
#include "vlayoutpiece.h" #include "vlayoutpiece.h"
@ -239,6 +243,10 @@ bool VLayoutPaper::ArrangeDetail(const VLayoutPiece &detail, std::atomic_bool &s
d->localRotationNumber = d->globalRotationNumber; d->localRotationNumber = d->globalRotationNumber;
} }
#ifdef LAYOUT_DEBUG
QMutex mutex;
#endif
VPositionData data; VPositionData data;
data.gContour = d->globalContour; data.gContour = d->globalContour;
data.detail = detail; data.detail = detail;
@ -247,9 +255,17 @@ bool VLayoutPaper::ArrangeDetail(const VLayoutPiece &detail, std::atomic_bool &s
data.followGrainline = d->followGrainline; data.followGrainline = d->followGrainline;
data.positionsCache = d->positionsCache; data.positionsCache = d->positionsCache;
data.isOriginPaperOrientationPortrait = d->originPaperOrientation; data.isOriginPaperOrientationPortrait = d->originPaperOrientation;
#ifdef LAYOUT_DEBUG
data.details = d->details;
data.mutex = &mutex;
#endif
const VBestSquare result = VPosition::ArrangeDetail(data, &stop, d->saveLength); const VBestSquare result = VPosition::ArrangeDetail(data, &stop, d->saveLength);
#ifdef LAYOUT_DEBUG
return SaveResult(result, detail, &mutex);
#else
return SaveResult(result, detail); return SaveResult(result, detail);
#endif
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -259,7 +275,11 @@ int VLayoutPaper::Count() const
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VLayoutPaper::SaveResult(const VBestSquare &bestResult, const VLayoutPiece &detail) bool VLayoutPaper::SaveResult(const VBestSquare &bestResult, const VLayoutPiece &detail
#ifdef LAYOUT_DEBUG
, QMutex *mutex
#endif
)
{ {
if (bestResult.HasValidResult()) if (bestResult.HasValidResult())
{ {
@ -287,6 +307,12 @@ bool VLayoutPaper::SaveResult(const VBestSquare &bestResult, const VLayoutPiece
positionChache.boundingRect = VLayoutPiece::BoundingRect(layoutPoints); positionChache.boundingRect = VLayoutPiece::BoundingRect(layoutPoints);
positionChache.layoutAllowancePath = VLayoutPiece::PainterPath(layoutPoints); positionChache.layoutAllowancePath = VLayoutPiece::PainterPath(layoutPoints);
d->positionsCache.append(positionChache); d->positionsCache.append(positionChache);
#ifdef LAYOUT_DEBUG
# ifdef SHOW_BEST
VPosition::DumpFrame(d->globalContour, workDetail, mutex, d->details);
# endif
#endif
} }
else if (bestResult.IsTerminatedByException()) else if (bestResult.IsTerminatedByException())
{ {

View File

@ -44,6 +44,7 @@ class VLayoutPiece;
class QGraphicsRectItem; class QGraphicsRectItem;
class QRectF; class QRectF;
class QGraphicsItem; class QGraphicsItem;
class QMutex;
template <typename T> class QList; template <typename T> class QList;
template <typename T> class QVector; template <typename T> class QVector;
@ -107,7 +108,11 @@ public:
private: private:
QSharedDataPointer<VLayoutPaperData> d; QSharedDataPointer<VLayoutPaperData> d;
bool SaveResult(const VBestSquare &bestResult, const VLayoutPiece &detail); bool SaveResult(const VBestSquare &bestResult, const VLayoutPiece &detail
#ifdef LAYOUT_DEBUG
, QMutex *mutex
#endif
);
}; };

View File

@ -61,6 +61,85 @@
#include <QScopeGuard> #include <QScopeGuard>
#endif #endif
namespace
{
#ifdef LAYOUT_DEBUG
//---------------------------------------------------------------------------------------------------------------------
QPainterPath ShowDirection(const QLineF &edge)
{
const int arrowLength = 14;
QPainterPath path;
if (edge.length()/arrowLength < 5)
{
return path;
}
QLineF arrow = edge;
arrow.setLength(edge.length()/2.0);
//Reverse line because we want start arrow from this point
arrow = QLineF(arrow.p2(), arrow.p1());
const qreal angle = arrow.angle();//we each time change line angle, better save original angle value
arrow.setLength(arrowLength);//arrow length in pixels
arrow.setAngle(angle-35);
path.moveTo(arrow.p1());
path.lineTo(arrow.p2());
arrow.setAngle(angle+35);
path.moveTo(arrow.p1());
path.lineTo(arrow.p2());
return path;
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath DumpContour(const QVector<QPointF> &points)
{
QPainterPath path;
path.setFillRule(Qt::WindingFill);
if (points.count() >= 2)
{
for (qint32 i = 0; i < points.count()-1; ++i)
{
path.moveTo(points.at(i));
path.lineTo(points.at(i+1));
}
path.lineTo(points.at(0));
#ifdef SHOW_DIRECTION
for (qint32 i = 0; i < points.count()-1; ++i)
{
path.addPath(ShowDirection(QLineF(points.at(i), points.at(i+1))));
}
#endif
#ifdef SHOW_VERTICES
for (qint32 i = 0; i < points.count(); ++i)
{
path.addRect(points.at(i).x()-3, points.at(i).y()-3, 6, 6);
}
#endif
}
return path;
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath DumpDetails(const QVector<VLayoutPiece> &details)
{
QPainterPath path;
path.setFillRule(Qt::WindingFill);
if (details.count() > 0)
{
for (auto &detail : details)
{
path.addPath(detail.ContourPath());
}
}
return path;
}
#endif
} //anonymous namespace
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPosition::VPosition() VPosition::VPosition()
{} {}
@ -246,6 +325,12 @@ bool VPosition::CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge)
CombineEdges(detail, globalEdge, dEdge); CombineEdges(detail, globalEdge, dEdge);
#ifdef LAYOUT_DEBUG
# ifdef SHOW_COMBINE
DumpFrame(m_data.gContour, detail, m_data.mutex, m_data.details);
# endif
#endif
CrossingType type = CrossingType::Intersection; CrossingType type = CrossingType::Intersection;
if (not detail.IsForceFlipping() && SheetContains(detail.DetailBoundingRect())) if (not detail.IsForceFlipping() && SheetContains(detail.DetailBoundingRect()))
{ {
@ -276,6 +361,12 @@ bool VPosition::CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge)
if (flagMirror && not detail.IsForbidFlipping()) if (flagMirror && not detail.IsForbidFlipping())
{ {
#ifdef LAYOUT_DEBUG
# ifdef SHOW_MIRROR
DumpFrame(m_data.gContour, detail, m_data.mutex, m_data.details);
# endif
#endif
dEdge = detail.LayoutEdgeByPoint(globalEdge.p2()); dEdge = detail.LayoutEdgeByPoint(globalEdge.p2());
if (dEdge <= 0) if (dEdge <= 0)
@ -319,6 +410,12 @@ bool VPosition::CheckRotationEdges(VLayoutPiece &detail, int j, int dEdge, qreal
RotateEdges(detail, globalEdge, dEdge, angle); RotateEdges(detail, globalEdge, dEdge, angle);
#ifdef LAYOUT_DEBUG
# ifdef SHOW_ROTATION
DumpFrame(m_data.gContour, detail, m_data.mutex, m_data.details);
# endif
#endif
CrossingType type = CrossingType::Intersection; CrossingType type = CrossingType::Intersection;
if (SheetContains(detail.DetailBoundingRect())) if (SheetContains(detail.DetailBoundingRect()))
{ {
@ -349,6 +446,12 @@ void VPosition::RotateOnAngle(qreal angle)
if (CheckRotationEdges(workDetail, m_data.j, m_data.i, angle)) if (CheckRotationEdges(workDetail, m_data.j, m_data.i, angle))
{ {
#ifdef LAYOUT_DEBUG
# ifdef SHOW_CANDIDATE_BEST
DumpFrame(m_data.gContour, workDetail, m_data.mutex, m_data.details);
# endif
#endif
SaveCandidate(m_bestResult, workDetail, m_data.j, m_data.i, BestFrom::Rotation); SaveCandidate(m_bestResult, workDetail, m_data.j, m_data.i, BestFrom::Rotation);
} }
} }
@ -497,6 +600,12 @@ void VPosition::FindBestPosition()
int dEdge = m_data.i;// For mirror detail edge will be different int dEdge = m_data.i;// For mirror detail edge will be different
if (CheckCombineEdges(workDetail, m_data.j, dEdge)) if (CheckCombineEdges(workDetail, m_data.j, dEdge))
{ {
#ifdef LAYOUT_DEBUG
# ifdef SHOW_CANDIDATE_BEST
DumpFrame(m_data.gContour, workDetail, m_data.mutex, m_data.details);
# endif
#endif
SaveCandidate(m_bestResult, workDetail, m_data.j, dEdge, BestFrom::Combine); SaveCandidate(m_bestResult, workDetail, m_data.j, dEdge, BestFrom::Combine);
} }
@ -515,3 +624,92 @@ void VPosition::FindBestPosition()
FollowGrainline(); FollowGrainline();
} }
} }
#ifdef LAYOUT_DEBUG
//---------------------------------------------------------------------------------------------------------------------
void VPosition::DumpFrame(const VContour &contour, const VLayoutPiece &detail, QMutex *mutex,
const QVector<VLayoutPiece> &details = QVector<VLayoutPiece>())
{
auto Bias = [](int length, int maxLength)
{
return length < maxLength && length*2 < maxLength ? length : maxLength-length;
};
const int biasWidth = Bias(contour.GetWidth(), QIMAGE_MAX);
const int biasHeight = Bias(contour.GetHeight(), QIMAGE_MAX);
QPicture picture;
QPainter paint;
paint.begin(&picture);
paint.setPen(QPen(Qt::black, 6, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
QPainterPath p;
if (contour.GetContour().isEmpty())
{
p = DumpContour(contour.CutEmptySheetEdge());
p.translate(biasWidth/2, biasHeight/2);
paint.drawPath(p);
}
else
{
p = DumpContour(contour.GetContour());
p.translate(biasWidth/2, biasHeight/2);
paint.drawPath(p);
}
#ifdef SHOW_CANDIDATE
paint.setPen(QPen(Qt::darkGreen, 6, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
p = DumpContour(detail.GetLayoutAllowancePoints());
p.translate(biasWidth/2, biasHeight/2);
paint.drawPath(p);
#else
Q_UNUSED(detail)
Q_UNUSED(details)
#endif
#ifdef ARRANGED_DETAILS
paint.setPen(QPen(Qt::blue, 2, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
p = DumpDetails(details);
p.translate(biasWidth/2, biasHeight/2);
paint.drawPath(p);
#else
Q_UNUSED(details)
#endif
// Calculate bounding rect before draw sheet rect
const QRect pictureRect = picture.boundingRect();
// Sheet
#ifdef SHOW_SHEET
paint.setPen(QPen(Qt::darkRed, 15, Qt::SolidLine, Qt::FlatCap, Qt::MiterJoin));
paint.drawRect(QRectF(biasWidth/2, biasHeight/2, contour.GetWidth(), contour.GetHeight()));
#endif
paint.end();
// Dump frame to image
// Note. If program was build with Address Sanitizer possible crashes. Address Sanitizer doesn't support big
// allocations. See page https://bitbucket.org/dismine/valentina/wiki/developers/Address_Sanitizer
QImage frameImage(pictureRect.width()+biasWidth, pictureRect.height()+biasHeight, QImage::Format_RGB32);
if (frameImage.isNull())
{
return;
}
frameImage.fill(Qt::white);
QPainter paintFrameImage;
paintFrameImage.begin(&frameImage);
paintFrameImage.drawPicture(0, 0, picture);
paintFrameImage.end();
QMutexLocker locker(mutex);
static int frame = 0;
++frame;
const QString path = QDir::homePath()+QStringLiteral("/LayoutDebug/%1.png").arg(frame);
frameImage.save (path);
}
#endif

View File

@ -35,6 +35,10 @@
#include <QtGlobal> #include <QtGlobal>
#include <atomic> #include <atomic>
#ifdef LAYOUT_DEBUG
#include <QMutex>
#endif
#include "vbestsquare.h" #include "vbestsquare.h"
#include "vcontour.h" #include "vcontour.h"
#include "vlayoutdef.h" #include "vlayoutdef.h"
@ -51,6 +55,10 @@ struct VPositionData
bool followGrainline{false}; bool followGrainline{false};
QVector<VCachedPositions> positionsCache{}; QVector<VCachedPositions> positionsCache{};
bool isOriginPaperOrientationPortrait{true}; bool isOriginPaperOrientationPortrait{true};
#ifdef LAYOUT_DEBUG
QVector<VLayoutPiece> details{};
QMutex *mutex{nullptr};
#endif
}; };
QT_WARNING_PUSH QT_WARNING_PUSH
@ -72,6 +80,11 @@ public:
static VBestSquare ArrangeDetail(const VPositionData &data, std::atomic_bool *stop, bool saveLength); static VBestSquare ArrangeDetail(const VPositionData &data, std::atomic_bool *stop, bool saveLength);
#ifdef LAYOUT_DEBUG
static void DumpFrame(const VContour &contour, const VLayoutPiece &detail, QMutex *mutex,
const QVector<VLayoutPiece> &details);
#endif
private: private:
bool m_isValid{false}; bool m_isValid{false};
VBestSquare m_bestResult{}; VBestSquare m_bestResult{};