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));
}
}
//---------------------------------------------------------------------------------------------------------------------
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;
#endif
DialogLayoutProgress *progress = new DialogLayoutProgress(timer, lGenerator.GetNestingTime()*1000, this);
QScopedPointer<DialogLayoutProgress> progress(new DialogLayoutProgress(timer, lGenerator.GetNestingTime()*60000,
this));
if (VApplication::IsGUIMode())
{
#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);
connect(progressTimer, &QTimer::timeout, this, [timer, &lGenerator]()
{
const qint64 elapsed = timer.elapsed();
const int timeout = static_cast<int>(lGenerator.GetNestingTime() * 1000 - elapsed);
m_taskbarProgress->setValue(static_cast<int>(elapsed/1000));
m_taskbarProgress->setValue(static_cast<int>(timer.elapsed()/60000));
});
progressTimer->start(1000);
#endif
connect(progress, &DialogLayoutProgress::Abort, &lGenerator, &VLayoutGenerator::Abort);
connect(progress.data(), &DialogLayoutProgress::Abort, &lGenerator, &VLayoutGenerator::Abort);
}
progress->Start();
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;
progress->Finished();
@ -268,10 +250,13 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
bool rotationUsed = false;
int rotatate = 1;
lGenerator.SetShift(BiggestEdge(listDetails) + 1);
lGenerator.SetShift(-1); // Trigger first shift calulation
lGenerator.SetRotate(false);
int papersCount = INT_MAX;
qreal efficiency = 0;
QCoreApplication::processEvents();
forever
{
if (IsTimeout())
@ -279,22 +264,20 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
break;
}
lGenerator.Generate();
lGenerator.Generate(timer, lGenerator.GetNestingTime()*60000);
if (IsTimeout())
{
break;
}
nestingState = lGenerator.State();
switch (nestingState)
switch (lGenerator.State())
{
case LayoutErrors::NoError:
if (lGenerator.PapersCount() <= papersCount)
{
const qreal layoutEfficiency = lGenerator.LayoutEfficiency();
if (efficiency > layoutEfficiency)
if (efficiency < layoutEfficiency)
{
efficiency = layoutEfficiency;
progress->Efficiency(efficiency);
@ -320,6 +303,8 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
lGenerator.SetShift(lGenerator.GetShift()/2.0);
break;
case LayoutErrors::EmptyPaperError:
if (lGenerator.IsRotationNeeded())
{
if (not rotationUsed)
{
lGenerator.SetRotate(true);
@ -331,16 +316,21 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
lGenerator.SetShift(lGenerator.GetShift()/2.0);
rotationUsed = false;
}
}
else
{
lGenerator.SetShift(lGenerator.GetShift()/2.0);
}
break;
case LayoutErrors::Timeout:
Q_UNREACHABLE();
break;
case LayoutErrors::PrepareLayoutError:
case LayoutErrors::ProcessStoped:
default:
break;
}
nestingState = lGenerator.State();
if (nestingState == LayoutErrors::PrepareLayoutError || nestingState == LayoutErrors::ProcessStoped
|| (nestingState == LayoutErrors::NoError && not qFuzzyIsNull(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 (VApplication::IsGUIMode())
{
@ -367,7 +359,7 @@ bool MainWindowsNoGUI::GenerateLayout(VLayoutGenerator& lGenerator)
QApplication::alert(this);
}
if (nestingState == LayoutErrors::NoError)
if (nestingState == LayoutErrors::NoError || (nestingState == LayoutErrors::Timeout && not papers.isEmpty()))
{
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)
{
@ -193,10 +215,12 @@ bool VBank::Prepare()
}
diagonal = 0;
for (int i=0; i < details.size(); ++i)
{
details[i].SetLayoutWidth(layoutWidth);
details[i].SetLayoutAllowancePoints();
if (not details.at(i).IsLayoutAllowanceValid())
{
const QString errorMsg = QObject::tr("Piece '%1' has invalid layout allowance. Please, check seam allowance"
@ -209,19 +233,7 @@ bool VBank::Prepare()
{
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;
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)
#pragma pop_macro("small")
#endif

View File

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

View File

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

View File

@ -52,6 +52,7 @@ class QMarginsF;
class QGraphicsItem;
class VLayoutPaper;
class QElapsedTimer;
class VLayoutGenerator :public QObject
{
@ -84,7 +85,7 @@ public:
qreal GetShift() const;
void SetShift(qreal shift);
void Generate();
void Generate(QElapsedTimer timer, qint64 timeout);
qreal LayoutEfficiency() const;
@ -125,6 +126,8 @@ public:
bool IsTestAsPaths() const;
void SetTextAsPaths(bool value);
bool IsRotationNeeded() const;
public slots:
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)
{
QCoreApplication::processEvents();
for (int i=1; i<= detailEdgesCount; ++i)
{
VPositionData data;
@ -431,8 +433,10 @@ qreal VLayoutPaper::Efficiency() const
qreal efficiency = 0;
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;
}