Check timeout inside the layout generator.

--HG--
branch : feature
This commit is contained in:
Roman Telezhynskyi 2019-03-30 11:17:54 +02:00
parent 4d75ca0fe3
commit 69df0922af
6 changed files with 178 additions and 67 deletions

View File

@ -123,22 +123,6 @@ void InsertGlobalContours(const QList<QGraphicsScene *> &scenes, const QList<QGr
scenes.at(i)->addItem(gcontours.at(i)); scenes.at(i)->addItem(gcontours.at(i));
} }
} }
//---------------------------------------------------------------------------------------------------------------------
qreal BiggestEdge(const QVector<VLayoutPiece> &pieces)
{
qreal edge = 0;
for(auto &piece : pieces)
{
const qreal pieceEdge = piece.BiggestEdge();
if (pieceEdge > edge)
{
edge = pieceEdge;
}
}
return edge;
}
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -231,7 +215,8 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
QTimer *progressTimer = nullptr; QTimer *progressTimer = nullptr;
#endif #endif
DialogLayoutProgress *progress = new DialogLayoutProgress(timer, lGenerator.GetNestingTime()*1000, this); QScopedPointer<DialogLayoutProgress> progress(new DialogLayoutProgress(timer, lGenerator.GetNestingTime()*60000,
this));
if (VApplication::IsGUIMode()) if (VApplication::IsGUIMode())
{ {
#if defined(Q_OS_WIN32) && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) #if defined(Q_OS_WIN32) && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
@ -241,23 +226,20 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
progressTimer = new QTimer(this); progressTimer = new QTimer(this);
connect(progressTimer, &QTimer::timeout, this, [timer, &lGenerator]() connect(progressTimer, &QTimer::timeout, this, [timer, &lGenerator]()
{ {
const qint64 elapsed = timer.elapsed(); m_taskbarProgress->setValue(static_cast<int>(timer.elapsed()/60000));
const int timeout = static_cast<int>(lGenerator.GetNestingTime() * 1000 - elapsed);
m_taskbarProgress->setValue(static_cast<int>(elapsed/1000));
}); });
progressTimer->start(1000); progressTimer->start(1000);
#endif #endif
connect(progress, &DialogLayoutProgress::Abort, &lGenerator, &VLayoutGenerator::Abort); connect(progress.data(), &DialogLayoutProgress::Abort, &lGenerator, &VLayoutGenerator::Abort);
} }
progress->Start(); progress->Start();
LayoutErrors nestingState = LayoutErrors::NoError; LayoutErrors nestingState = LayoutErrors::NoError;
auto IsTimeout = [progress, &lGenerator, timer, &nestingState]() auto IsTimeout = [&progress, &lGenerator, timer, &nestingState]()
{ {
if (lGenerator.GetNestingTime() * 1000 - timer.elapsed() <= 0) if (timer.hasExpired(lGenerator.GetNestingTime() * 60000))
{ {
nestingState = LayoutErrors::Timeout; nestingState = LayoutErrors::Timeout;
progress->Finished(); progress->Finished();
@ -268,10 +250,13 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
bool rotationUsed = false; bool rotationUsed = false;
int rotatate = 1; int rotatate = 1;
lGenerator.SetShift(BiggestEdge(listDetails) + 1); lGenerator.SetShift(-1); // Trigger first shift calulation
lGenerator.SetRotate(false);
int papersCount = INT_MAX; int papersCount = INT_MAX;
qreal efficiency = 0; qreal efficiency = 0;
QCoreApplication::processEvents();
forever forever
{ {
if (IsTimeout()) if (IsTimeout())
@ -279,22 +264,20 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
break; break;
} }
lGenerator.Generate(); lGenerator.Generate(timer, lGenerator.GetNestingTime()*60000);
if (IsTimeout()) if (IsTimeout())
{ {
break; break;
} }
nestingState = lGenerator.State(); switch (lGenerator.State())
switch (nestingState)
{ {
case LayoutErrors::NoError: case LayoutErrors::NoError:
if (lGenerator.PapersCount() <= papersCount) if (lGenerator.PapersCount() <= papersCount)
{ {
const qreal layoutEfficiency = lGenerator.LayoutEfficiency(); const qreal layoutEfficiency = lGenerator.LayoutEfficiency();
if (efficiency > layoutEfficiency) if (efficiency < layoutEfficiency)
{ {
efficiency = layoutEfficiency; efficiency = layoutEfficiency;
progress->Efficiency(efficiency); progress->Efficiency(efficiency);
@ -320,27 +303,34 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
lGenerator.SetShift(lGenerator.GetShift()/2.0); lGenerator.SetShift(lGenerator.GetShift()/2.0);
break; break;
case LayoutErrors::EmptyPaperError: case LayoutErrors::EmptyPaperError:
if (not rotationUsed) if (lGenerator.IsRotationNeeded())
{ {
lGenerator.SetRotate(true); if (not rotationUsed)
lGenerator.SetRotationNumber(++rotatate); {
rotationUsed = true; lGenerator.SetRotate(true);
lGenerator.SetRotationNumber(++rotatate);
rotationUsed = true;
}
else
{
lGenerator.SetShift(lGenerator.GetShift()/2.0);
rotationUsed = false;
}
} }
else else
{ {
lGenerator.SetShift(lGenerator.GetShift()/2.0); lGenerator.SetShift(lGenerator.GetShift()/2.0);
rotationUsed = false;
} }
break; break;
case LayoutErrors::Timeout: case LayoutErrors::Timeout:
Q_UNREACHABLE();
break;
case LayoutErrors::PrepareLayoutError: case LayoutErrors::PrepareLayoutError:
case LayoutErrors::ProcessStoped: case LayoutErrors::ProcessStoped:
default: default:
break; break;
} }
nestingState = lGenerator.State();
if (nestingState == LayoutErrors::PrepareLayoutError || nestingState == LayoutErrors::ProcessStoped if (nestingState == LayoutErrors::PrepareLayoutError || nestingState == LayoutErrors::ProcessStoped
|| (nestingState == LayoutErrors::NoError && not qFuzzyIsNull(lGenerator.GetEfficiencyCoefficient()) || (nestingState == LayoutErrors::NoError && not qFuzzyIsNull(lGenerator.GetEfficiencyCoefficient())
&& efficiency >= lGenerator.GetEfficiencyCoefficient())) && efficiency >= lGenerator.GetEfficiencyCoefficient()))
@ -354,6 +344,8 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
} }
} }
progress->Finished();
#if defined(Q_OS_WIN32) && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) #if defined(Q_OS_WIN32) && QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
if (VApplication::IsGUIMode()) if (VApplication::IsGUIMode())
{ {
@ -367,7 +359,7 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
QApplication::alert(this); QApplication::alert(this);
} }
if (nestingState == LayoutErrors::NoError) if (nestingState == LayoutErrors::NoError || (nestingState == LayoutErrors::Timeout && not papers.isEmpty()))
{ {
return true; return true;
} }

View File

@ -176,7 +176,29 @@ void VBank::NotArranged(int i)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VBank::Prepare() bool VBank::PrepareUnsorted()
{
for (int i=0; i < details.size(); ++i)
{
const qint64 square = details.at(i).Square();
if (square <= 0)
{
qCCritical(lBank, "Preparing data for layout error: Detail '%s' square <= 0",
qUtf8Printable(details.at(i).GetName()));
prepare = false;
return prepare;
}
unsorted.insert(i, square);
}
PrepareGroup();
prepare = true;
return prepare;
}
//---------------------------------------------------------------------------------------------------------------------
bool VBank::PrepareDetails()
{ {
if (layoutWidth <= 0) if (layoutWidth <= 0)
{ {
@ -193,10 +215,12 @@ bool VBank::Prepare()
} }
diagonal = 0; diagonal = 0;
for (int i=0; i < details.size(); ++i) for (int i=0; i < details.size(); ++i)
{ {
details[i].SetLayoutWidth(layoutWidth); details[i].SetLayoutWidth(layoutWidth);
details[i].SetLayoutAllowancePoints(); details[i].SetLayoutAllowancePoints();
if (not details.at(i).IsLayoutAllowanceValid()) if (not details.at(i).IsLayoutAllowanceValid())
{ {
const QString errorMsg = QObject::tr("Piece '%1' has invalid layout allowance. Please, check seam allowance" const QString errorMsg = QObject::tr("Piece '%1' has invalid layout allowance. Please, check seam allowance"
@ -209,20 +233,8 @@ bool VBank::Prepare()
{ {
diagonal = d; diagonal = d;
} }
const qint64 square = details.at(i).Square();
if (square <= 0)
{
qCCritical(lBank, "Preparing data for layout error: Detail '%s' square <= 0",
qUtf8Printable(details.at(i).GetName()));
prepare = false;
return prepare;
}
unsorted.insert(i, square);
} }
PrepareGroup();
prepare = true; prepare = true;
return prepare; return prepare;
} }
@ -436,6 +448,35 @@ void VBank::SqMaxMin(qint64 &sMax, qint64 &sMin) const
} }
//---------------------------------------------------------------------------------------------------------------------
qreal VBank::DetailsBiggestEdge() const
{
qreal edge = 0;
for(auto &piece : details)
{
const qreal pieceEdge = piece.BiggestEdge();
if (pieceEdge > edge)
{
edge = pieceEdge;
}
}
return edge;
}
//---------------------------------------------------------------------------------------------------------------------
bool VBank::IsRotationNeeded() const
{
for(auto &piece : details)
{
if (not piece.IsGrainlineEnabled())
{
return true;
}
}
return false;
}
#if defined (Q_OS_WIN) && defined (Q_CC_MSVC) #if defined (Q_OS_WIN) && defined (Q_CC_MSVC)
#pragma pop_macro("small") #pragma pop_macro("small")
#endif #endif

View File

@ -54,6 +54,7 @@ public:
qreal GetLayoutWidth() const; qreal GetLayoutWidth() const;
void SetLayoutWidth(qreal value); void SetLayoutWidth(qreal value);
void SetDetails(const QVector<VLayoutPiece> &details); void SetDetails(const QVector<VLayoutPiece> &details);
int GetNext(); int GetNext();
VLayoutPiece GetDetail(int i) const; VLayoutPiece GetDetail(int i) const;
@ -61,7 +62,8 @@ public:
void Arranged(int i); void Arranged(int i);
void NotArranged(int i); void NotArranged(int i);
bool Prepare(); bool PrepareUnsorted();
bool PrepareDetails();
void Reset(); void Reset();
void SetCaseType(Cases caseType); void SetCaseType(Cases caseType);
@ -70,6 +72,9 @@ public:
int ArrangedCount() const; int ArrangedCount() const;
qreal GetBiggestDiagonal() const; qreal GetBiggestDiagonal() const;
qreal DetailsBiggestEdge() const;
bool IsRotationNeeded() const;
private: private:
Q_DISABLE_COPY(VBank) Q_DISABLE_COPY(VBank)

View File

@ -28,6 +28,7 @@
#include "vlayoutgenerator.h" #include "vlayoutgenerator.h"
#include <QElapsedTimer>
#include <QGraphicsRectItem> #include <QGraphicsRectItem>
#include <QRectF> #include <QRectF>
#include <QThreadPool> #include <QThreadPool>
@ -98,21 +99,25 @@ int VLayoutGenerator::DetailsCount()
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VLayoutGenerator::Generate() void VLayoutGenerator::Generate(QElapsedTimer timer, qint64 timeout)
{ {
stopGeneration.store(false); stopGeneration.store(false);
papers.clear(); papers.clear();
bank->Reset();
state = LayoutErrors::NoError; state = LayoutErrors::NoError;
#ifdef LAYOUT_DEBUG if (VFuzzyComparePossibleNulls(shift, -1))
const QString path = QDir::homePath()+QStringLiteral("/LayoutDebug");
QDir debugDir(path);
debugDir.removeRecursively();
debugDir.mkpath(path);
#endif
if (bank->Prepare())
{ {
if (bank->PrepareDetails())
{
SetShift(bank->DetailsBiggestEdge() + 1);
}
else
{
state = LayoutErrors::PrepareLayoutError;
return;
}
int width = PageWidth(); int width = PageWidth();
int height = PageHeight(); int height = PageHeight();
@ -131,15 +136,43 @@ void VLayoutGenerator::Generate()
IsPortrait() ? SetStrip(height) : SetStrip(width); IsPortrait() ? SetStrip(height) : SetStrip(width);
} }
}
if (timer.hasExpired(timeout))
{
state = LayoutErrors::Timeout;
return;
}
#ifdef LAYOUT_DEBUG
const QString path = QDir::homePath()+QStringLiteral("/LayoutDebug");
QDir debugDir(path);
debugDir.removeRecursively();
debugDir.mkpath(path);
#endif
if (bank->PrepareUnsorted())
{
if (timer.hasExpired(timeout))
{
state = LayoutErrors::Timeout;
return;
}
while (bank->AllDetailsCount() > 0) while (bank->AllDetailsCount() > 0)
{ {
if (stopGeneration.load()) if (stopGeneration.load())
{ {
break; return;
} }
VLayoutPaper paper(height, width, bank->GetLayoutWidth()); if (timer.hasExpired(timeout))
{
state = LayoutErrors::Timeout;
return;
}
VLayoutPaper paper(PageHeight(), PageWidth(), bank->GetLayoutWidth());
paper.SetShift(shift); paper.SetShift(shift);
paper.SetPaperIndex(static_cast<quint32>(papers.count())); paper.SetPaperIndex(static_cast<quint32>(papers.count()));
paper.SetRotate(rotate); paper.SetRotate(rotate);
@ -158,15 +191,29 @@ void VLayoutGenerator::Generate()
bank->NotArranged(index); bank->NotArranged(index);
} }
QCoreApplication::processEvents();
if (stopGeneration.load()) if (stopGeneration.load())
{ {
break; break;
} }
if (timer.hasExpired(timeout))
{
state = LayoutErrors::Timeout;
return;
}
} while(bank->LeftToArrange() > 0); } while(bank->LeftToArrange() > 0);
if (stopGeneration.load()) if (stopGeneration.load())
{ {
break; return;
}
if (timer.hasExpired(timeout))
{
state = LayoutErrors::Timeout;
return;
} }
if (paper.Count() > 0) if (paper.Count() > 0)
@ -186,6 +233,12 @@ void VLayoutGenerator::Generate()
return; return;
} }
if (timer.hasExpired(timeout))
{
state = LayoutErrors::Timeout;
return;
}
if (stripOptimizationEnabled) if (stripOptimizationEnabled)
{ {
GatherPages(); GatherPages();
@ -295,6 +348,19 @@ void VLayoutGenerator::SetTextAsPaths(bool value)
textAsPaths = value; textAsPaths = value;
} }
//---------------------------------------------------------------------------------------------------------------------
bool VLayoutGenerator::IsRotationNeeded() const
{
if (followGrainline)
{
return bank->IsRotationNeeded();
}
else
{
return true;
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
quint8 VLayoutGenerator::GetMultiplier() const quint8 VLayoutGenerator::GetMultiplier() const
{ {

View File

@ -52,6 +52,7 @@ class QMarginsF;
class QGraphicsItem; class QGraphicsItem;
class VLayoutPaper; class VLayoutPaper;
class QElapsedTimer;
class VLayoutGenerator :public QObject class VLayoutGenerator :public QObject
{ {
@ -84,7 +85,7 @@ public:
qreal GetShift() const; qreal GetShift() const;
void SetShift(qreal shift); void SetShift(qreal shift);
void Generate(); void Generate(QElapsedTimer timer, qint64 timeout);
qreal LayoutEfficiency() const; qreal LayoutEfficiency() const;
@ -125,6 +126,8 @@ public:
bool IsTestAsPaths() const; bool IsTestAsPaths() const;
void SetTextAsPaths(bool value); void SetTextAsPaths(bool value);
bool IsRotationNeeded() const;
public slots: public slots:
void Abort(); void Abort();

View File

@ -240,6 +240,8 @@ bool VLayoutPaper::AddToSheet(const VLayoutPiece &detail, std::atomic_bool &stop
for (int j=1; j <= d->globalContour.GlobalEdgesCount(); ++j) for (int j=1; j <= d->globalContour.GlobalEdgesCount(); ++j)
{ {
QCoreApplication::processEvents();
for (int i=1; i<= detailEdgesCount; ++i) for (int i=1; i<= detailEdgesCount; ++i)
{ {
VPositionData data; VPositionData data;
@ -431,8 +433,10 @@ qreal VLayoutPaper::Efficiency() const
qreal efficiency = 0; qreal efficiency = 0;
for(auto &detail : d->details) for(auto &detail : d->details)
{ {
efficiency += detail.Square(); efficiency += static_cast<qreal>(detail.Square());
} }
return efficiency / (d->globalContour.GetWidth() * d->globalContour.GetHeight()) * 100; const QRectF boundingRect = DetailsBoundingRect();
return efficiency / (boundingRect.width() * boundingRect.height()) * 100.0;
} }