Refactoring. Pass position data as struct.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2019-03-26 18:54:59 +02:00
parent 93334c7f7d
commit 81cda14c06
3 changed files with 122 additions and 94 deletions

View File

@ -238,23 +238,23 @@ bool VLayoutPaper::AddToSheet(const VLayoutPiece &detail, std::atomic_bool &stop
thread_pool->setExpiryTimeout(1000); thread_pool->setExpiryTimeout(1000);
QVector<VPosition *> threads; QVector<VPosition *> threads;
int detailEdgesCount = 0; int detailEdgesCount = d->globalContour.GetContour().isEmpty() ? detail.DetailEdgesCount() :
detail.LayoutEdgesCount();
if (d->globalContour.GetContour().isEmpty())
{
detailEdgesCount = detail.DetailEdgesCount();
}
else
{
detailEdgesCount = detail.LayoutEdgesCount();
}
for (int j=1; j <= d->globalContour.GlobalEdgesCount(); ++j) for (int j=1; j <= d->globalContour.GlobalEdgesCount(); ++j)
{ {
for (int i=1; i<= detailEdgesCount; ++i) for (int i=1; i<= detailEdgesCount; ++i)
{ {
auto *thread = new VPosition(d->globalContour, j, detail, i, &stop, d->localRotate, VPositionData data;
d->localRotationIncrease, d->saveLength, d->followGrainline); data.gContour = d->globalContour;
data.detail = detail;
data.i = i;
data.j = j;
data.rotate = d->localRotate;
data.rotationIncrease = d->localRotationIncrease;
data.followGrainline = d->followGrainline;
auto *thread = new VPosition(data, &stop, d->saveLength);
//Info for debug //Info for debug
#ifdef LAYOUT_DEBUG #ifdef LAYOUT_DEBUG
thread->setPaperIndex(d->paperIndex); thread->setPaperIndex(d->paperIndex);
@ -267,7 +267,9 @@ bool VLayoutPaper::AddToSheet(const VLayoutPiece &detail, std::atomic_bool &stop
threads.append(thread); threads.append(thread);
thread_pool->start(thread); thread_pool->start(thread);
#ifdef LAYOUT_DEBUG
d->frame = d->frame + 3 + static_cast<quint32>(360/d->localRotationIncrease*2); d->frame = d->frame + 3 + static_cast<quint32>(360/d->localRotationIncrease*2);
#endif
} }
} }

View File

@ -81,6 +81,7 @@ QPainterPath ShowDirection(const QLineF &edge)
} }
#endif #endif
#ifdef LAYOUT_DEBUG
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QPainterPath DrawContour(const QVector<QPointF> &points) QPainterPath DrawContour(const QVector<QPointF> &points)
{ {
@ -111,6 +112,7 @@ QPainterPath DrawContour(const QVector<QPointF> &points)
} }
return path; return path;
} }
#endif
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
#ifdef ARRANGED_DETAILS #ifdef ARRANGED_DETAILS
@ -132,27 +134,22 @@ QPainterPath DrawDetails(const QVector<VLayoutPiece> &details)
} //anonymous namespace } //anonymous namespace
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPosition::VPosition(const VContour &gContour, int j, const VLayoutPiece &detail, int i, std::atomic_bool *stop, VPosition::VPosition(const VPositionData &data, std::atomic_bool *stop, bool saveLength)
bool rotate, int rotationIncrease, bool saveLength, bool followGainline)
: QRunnable(), : QRunnable(),
bestResult(VBestSquare(gContour.GetSize(), saveLength)), m_bestResult(VBestSquare(data.gContour.GetSize(), saveLength)),
gContour(gContour), m_data(data),
detail(detail), #ifdef LAYOUT_DEBUG
i(i),
j(j),
paperIndex(0), paperIndex(0),
frame(0), frame(0),
detailsCount(0), detailsCount(0),
details(), details(),
#endif
stop(stop), stop(stop),
rotate(rotate), angle_between(0)
rotationIncrease(rotationIncrease),
angle_between(0),
followGrainline(followGainline)
{ {
if (not (rotationIncrease >= 1 && rotationIncrease <= 180 && 360 % rotationIncrease == 0)) if (not (m_data.rotationIncrease >= 1 && m_data.rotationIncrease <= 180 && 360 % m_data.rotationIncrease == 0))
{ {
this->rotationIncrease = 180; m_data.rotationIncrease = 180;
} }
} }
@ -164,42 +161,10 @@ void VPosition::run()
return; return;
} }
if (not followGrainline || not detail.IsGrainlineEnabled()) FindBestPosition();
{ }
// We should use copy of the detail.
VLayoutPiece workDetail = detail;
int dEdge = i;// For mirror detail edge will be different
if (CheckCombineEdges(workDetail, j, dEdge))
{
#ifdef LAYOUT_DEBUG #ifdef LAYOUT_DEBUG
# ifdef SHOW_CANDIDATE_BEST
DrawDebug(gContour, workDetail, frame+2, paperIndex, detailsCount, details);
# endif
#endif
SaveCandidate(bestResult, workDetail, j, dEdge, BestFrom::Combine);
}
frame = frame + 3;
if (rotate)
{
Rotate(rotationIncrease);
}
else
{
if (gContour.GetContour().isEmpty())
{
Rotate(rotationIncrease);
}
}
}
else
{
FollowGrainline();
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
// cppcheck-suppress unusedFunction // cppcheck-suppress unusedFunction
quint32 VPosition::getPaperIndex() const quint32 VPosition::getPaperIndex() const
@ -244,13 +209,15 @@ void VPosition::setDetails(const QVector<VLayoutPiece> &details)
{ {
this->details = details; this->details = details;
} }
#endif
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VBestSquare VPosition::getBestResult() const VBestSquare VPosition::getBestResult() const
{ {
return bestResult; return m_bestResult;
} }
#ifdef LAYOUT_DEBUG
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPosition::DrawDebug(const VContour &contour, const VLayoutPiece &detail, int frame, quint32 paperIndex, void VPosition::DrawDebug(const VContour &contour, const VLayoutPiece &detail, int frame, quint32 paperIndex,
int detailsCount, const QVector<VLayoutPiece> &details) int detailsCount, const QVector<VLayoutPiece> &details)
@ -334,16 +301,17 @@ int VPosition::Bias(int length, int maxLength)
{ {
return length < maxLength && length*2 < maxLength ? length : maxLength-length; return length < maxLength && length*2 < maxLength ? length : maxLength-length;
} }
#endif
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPosition::SaveCandidate(VBestSquare &bestResult, const VLayoutPiece &detail, int globalI, int detJ, void VPosition::SaveCandidate(VBestSquare &bestResult, const VLayoutPiece &detail, int globalI, int detJ,
BestFrom type) BestFrom type)
{ {
QVector<QPointF> newGContour = gContour.UniteWithContour(detail, globalI, detJ, type); QVector<QPointF> newGContour = m_data.gContour.UniteWithContour(detail, globalI, detJ, type);
newGContour.append(newGContour.first()); newGContour.append(newGContour.first());
const QSizeF size = QPolygonF(newGContour).boundingRect().size(); const QSizeF size = QPolygonF(newGContour).boundingRect().size();
const bool isPortrait = gContour.GetSize().height() >= gContour.GetSize().width(); const bool isPortrait = m_data.gContour.GetSize().height() >= m_data.gContour.GetSize().width();
const qreal position = isPortrait ? detail.DetailBoundingRect().y() : detail.DetailBoundingRect().x(); const qreal position = isPortrait ? detail.DetailBoundingRect().y() : detail.DetailBoundingRect().x();
bestResult.NewResult(size, globalI, detJ, detail.GetMatrix(), detail.IsMirror(), position, type); bestResult.NewResult(size, globalI, detJ, detail.GetMatrix(), detail.IsMirror(), position, type);
@ -352,7 +320,7 @@ void VPosition::SaveCandidate(VBestSquare &bestResult, const VLayoutPiece &detai
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VPosition::CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge) bool VPosition::CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge)
{ {
const QLineF globalEdge = gContour.GlobalEdge(j); const QLineF globalEdge = m_data.gContour.GlobalEdge(j);
bool flagMirror = false; bool flagMirror = false;
bool flagSquare = false; bool flagSquare = false;
@ -367,7 +335,7 @@ bool VPosition::CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge)
CrossingType type = CrossingType::Intersection; CrossingType type = CrossingType::Intersection;
if (not detail.IsForceFlipping() && SheetContains(detail.DetailBoundingRect())) if (not detail.IsForceFlipping() && SheetContains(detail.DetailBoundingRect()))
{ {
if (not gContour.GetContour().isEmpty()) if (not m_data.gContour.GetContour().isEmpty())
{ {
type = Crossing(detail); type = Crossing(detail);
} }
@ -400,7 +368,7 @@ bool VPosition::CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge)
#endif #endif
#endif #endif
if (gContour.GetContour().isEmpty()) if (m_data.gContour.GetContour().isEmpty())
{ {
dEdge = detail.DetailEdgeByPoint(globalEdge.p2()); dEdge = detail.DetailEdgeByPoint(globalEdge.p2());
} }
@ -440,12 +408,12 @@ bool VPosition::CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge)
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VPosition::CheckRotationEdges(VLayoutPiece &detail, int j, int dEdge, qreal angle) const bool VPosition::CheckRotationEdges(VLayoutPiece &detail, int j, int dEdge, qreal angle) const
{ {
const QLineF globalEdge = gContour.GlobalEdge(j); const QLineF globalEdge = m_data.gContour.GlobalEdge(j);
bool flagSquare = false; bool flagSquare = false;
if (detail.IsForceFlipping()) if (detail.IsForceFlipping())
{ {
detail.Mirror(not followGrainline ? globalEdge : QLineF(10, 10, 10, 100)); detail.Mirror(not m_data.followGrainline ? globalEdge : QLineF(10, 10, 10, 100));
} }
RotateEdges(detail, globalEdge, dEdge, angle); RotateEdges(detail, globalEdge, dEdge, angle);
@ -482,9 +450,9 @@ bool VPosition::CheckRotationEdges(VLayoutPiece &detail, int j, int dEdge, qreal
void VPosition::RotateOnAngle(qreal angle) void VPosition::RotateOnAngle(qreal angle)
{ {
// We should use copy of the detail. // We should use copy of the detail.
VLayoutPiece workDetail = detail; VLayoutPiece workDetail = m_data.detail;
if (CheckRotationEdges(workDetail, j, i, angle)) if (CheckRotationEdges(workDetail, m_data.j, m_data.i, angle))
{ {
#ifdef LAYOUT_DEBUG #ifdef LAYOUT_DEBUG
# ifdef SHOW_CANDIDATE_BEST # ifdef SHOW_CANDIDATE_BEST
@ -493,22 +461,24 @@ void VPosition::RotateOnAngle(qreal angle)
# endif # endif
#endif #endif
SaveCandidate(bestResult, workDetail, j, i, BestFrom::Rotation); SaveCandidate(m_bestResult, workDetail, m_data.j, m_data.i, BestFrom::Rotation);
} }
#ifdef LAYOUT_DEBUG
++frame; ++frame;
#endif
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VPosition::CrossingType VPosition::Crossing(const VLayoutPiece &detail) const VPosition::CrossingType VPosition::Crossing(const VLayoutPiece &detail) const
{ {
const QRectF gRect = gContour.BoundingRect(); const QRectF gRect = m_data.gContour.BoundingRect();
if (not gRect.intersects(detail.LayoutBoundingRect()) && not gRect.contains(detail.DetailBoundingRect())) if (not gRect.intersects(detail.LayoutBoundingRect()) && not gRect.contains(detail.DetailBoundingRect()))
{ {
// This we can determine efficiently. // This we can determine efficiently.
return CrossingType::NoIntersection; return CrossingType::NoIntersection;
} }
const QPainterPath gPath = gContour.ContourPath(); const QPainterPath gPath = m_data.gContour.ContourPath();
CrossingType crossing = CrossingType::EdgeError; CrossingType crossing = CrossingType::EdgeError;
if (not gPath.intersects(detail.LayoutAllowancePath()) && not gPath.contains(detail.ContourPath())) if (not gPath.intersects(detail.LayoutAllowancePath()) && not gPath.contains(detail.ContourPath()))
{ {
@ -524,7 +494,7 @@ VPosition::CrossingType VPosition::Crossing(const VLayoutPiece &detail) const
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
bool VPosition::SheetContains(const QRectF &rect) const bool VPosition::SheetContains(const QRectF &rect) const
{ {
const QRectF bRect(0, 0, gContour.GetWidth(), gContour.GetHeight()); const QRectF bRect(0, 0, m_data.gContour.GetWidth(), m_data.gContour.GetHeight());
return bRect.contains(rect); return bRect.contains(rect);
} }
@ -532,7 +502,7 @@ bool VPosition::SheetContains(const QRectF &rect) const
void VPosition::CombineEdges(VLayoutPiece &detail, const QLineF &globalEdge, int dEdge) void VPosition::CombineEdges(VLayoutPiece &detail, const QLineF &globalEdge, int dEdge)
{ {
QLineF detailEdge; QLineF detailEdge;
if (gContour.GetContour().isEmpty()) if (m_data.gContour.GetContour().isEmpty())
{ {
detailEdge = detail.DetailEdge(dEdge); detailEdge = detail.DetailEdge(dEdge);
} }
@ -561,7 +531,7 @@ void VPosition::CombineEdges(VLayoutPiece &detail, const QLineF &globalEdge, int
void VPosition::RotateEdges(VLayoutPiece &detail, const QLineF &globalEdge, int dEdge, qreal angle) const void VPosition::RotateEdges(VLayoutPiece &detail, const QLineF &globalEdge, int dEdge, qreal angle) const
{ {
QLineF detailEdge; QLineF detailEdge;
if (gContour.GetContour().isEmpty()) if (m_data.gContour.GetContour().isEmpty())
{ {
detailEdge = detail.DetailEdge(dEdge); detailEdge = detail.DetailEdge(dEdge);
} }
@ -609,24 +579,67 @@ void VPosition::FollowGrainline()
} }
QLineF detailGrainline(10, 10, 100, 10); QLineF detailGrainline(10, 10, 100, 10);
detailGrainline.setAngle(detail.GrainlineAngle()); detailGrainline.setAngle(m_data.detail.GrainlineAngle());
if (detail.IsForceFlipping()) if (m_data.detail.IsForceFlipping())
{ {
VLayoutPiece workDetail = detail; // We need copy for temp change VLayoutPiece workDetail = m_data.detail; // We need copy for temp change
workDetail.Mirror(not followGrainline ? gContour.GlobalEdge(j) : QLineF(10, 10, 10, 100)); workDetail.Mirror(not m_data.followGrainline ? m_data.gContour.GlobalEdge(m_data.j) : QLineF(10, 10, 10, 100));
detailGrainline = workDetail.GetMatrix().map(detailGrainline); detailGrainline = workDetail.GetMatrix().map(detailGrainline);
} }
const qreal angle = detailGrainline.angleTo(FabricGrainline()); const qreal angle = detailGrainline.angleTo(FabricGrainline());
if (detail.GrainlineArrowType() == ArrowType::atBoth || detail.GrainlineArrowType() == ArrowType::atFront) if (m_data.detail.GrainlineArrowType() == ArrowType::atBoth ||
m_data.detail.GrainlineArrowType() == ArrowType::atFront)
{ {
RotateOnAngle(angle); RotateOnAngle(angle);
} }
if (detail.GrainlineArrowType() == ArrowType::atBoth || detail.GrainlineArrowType() == ArrowType::atRear) if (m_data.detail.GrainlineArrowType() == ArrowType::atBoth ||
m_data.detail.GrainlineArrowType() == ArrowType::atRear)
{ {
RotateOnAngle(angle+180); RotateOnAngle(angle+180);
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void VPosition::FindBestPosition()
{
if (not m_data.followGrainline || not m_data.detail.IsGrainlineEnabled())
{
// We should use copy of the detail.
VLayoutPiece workDetail = m_data.detail;
int dEdge = m_data.i;// For mirror detail edge will be different
if (CheckCombineEdges(workDetail, m_data.j, dEdge))
{
#ifdef LAYOUT_DEBUG
# ifdef SHOW_CANDIDATE_BEST
DrawDebug(gContour, workDetail, frame+2, paperIndex, detailsCount, details);
# endif
#endif
SaveCandidate(m_bestResult, workDetail, m_data.j, dEdge, BestFrom::Combine);
}
#ifdef LAYOUT_DEBUG
frame = frame + 3;
#endif
if (m_data.rotate)
{
Rotate(m_data.rotationIncrease);
}
else
{
if (m_data.gContour.GetContour().isEmpty())
{
Rotate(m_data.rotationIncrease);
}
}
}
else
{
FollowGrainline();
}
}

View File

@ -40,13 +40,26 @@
#include "vlayoutdef.h" #include "vlayoutdef.h"
#include "vlayoutpiece.h" #include "vlayoutpiece.h"
struct VPositionData
{
VContour gContour{};
VLayoutPiece detail{};
int i{-1};
int j{-1};
bool rotate{false};
int rotationIncrease{0};
bool followGrainline{false};
};
class VPosition : public QRunnable class VPosition : public QRunnable
{ {
public: public:
VPosition(const VContour &gContour, int j, const VLayoutPiece &detail, int i, std::atomic_bool *stop, bool rotate, VPosition(const VPositionData &data, std::atomic_bool *stop, bool saveLength);
int rotationIncrease, bool saveLength, bool followGainline);
virtual ~VPosition() override = default; virtual ~VPosition() override = default;
virtual void run() override;
#ifdef LAYOUT_DEBUG
quint32 getPaperIndex() const; quint32 getPaperIndex() const;
void setPaperIndex(quint32 value); void setPaperIndex(quint32 value);
@ -57,33 +70,32 @@ public:
void setDetailsCount(quint32 value); void setDetailsCount(quint32 value);
void setDetails(const QVector<VLayoutPiece> &details); void setDetails(const QVector<VLayoutPiece> &details);
#endif
VBestSquare getBestResult() const; VBestSquare getBestResult() const;
#ifdef LAYOUT_DEBUG
static void DrawDebug(const VContour &contour, const VLayoutPiece &detail, int frame, quint32 paperIndex, static void DrawDebug(const VContour &contour, const VLayoutPiece &detail, int frame, quint32 paperIndex,
int detailsCount, const QVector<VLayoutPiece> &details = QVector<VLayoutPiece>()); int detailsCount, const QVector<VLayoutPiece> &details = QVector<VLayoutPiece>());
static int Bias(int length, int maxLength); static int Bias(int length, int maxLength);
#endif
private: private:
Q_DISABLE_COPY(VPosition) Q_DISABLE_COPY(VPosition)
VBestSquare bestResult; VBestSquare m_bestResult;
const VContour gContour; VPositionData m_data;
const VLayoutPiece detail; #ifdef LAYOUT_DEBUG
int i;
int j;
quint32 paperIndex; quint32 paperIndex;
quint32 frame; quint32 frame;
quint32 detailsCount; quint32 detailsCount;
QVector<VLayoutPiece> details; QVector<VLayoutPiece> details;
#endif
std::atomic_bool *stop; std::atomic_bool *stop;
bool rotate;
int rotationIncrease;
/** /**
* @brief angle_between keep angle between global edge and detail edge. Need for optimization rotation. * @brief angle_between keep angle between global edge and detail edge. Need for optimization rotation.
*/ */
qreal angle_between; qreal angle_between;
bool followGrainline;
enum class CrossingType : char enum class CrossingType : char
{ {
@ -99,8 +111,6 @@ private:
EdgeError = 2 EdgeError = 2
}; };
virtual void run() override;
void SaveCandidate(VBestSquare &bestResult, const VLayoutPiece &detail, int globalI, int detJ, BestFrom type); void SaveCandidate(VBestSquare &bestResult, const VLayoutPiece &detail, int globalI, int detJ, BestFrom type);
bool CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge); bool CheckCombineEdges(VLayoutPiece &detail, int j, int &dEdge);
@ -118,6 +128,8 @@ private:
void FollowGrainline(); void FollowGrainline();
QLineF FabricGrainline() const; QLineF FabricGrainline() const;
void FindBestPosition();
}; };
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -127,7 +139,8 @@ private:
*/ */
inline QLineF VPosition::FabricGrainline() const inline QLineF VPosition::FabricGrainline() const
{ {
return gContour.GetHeight() >= gContour.GetWidth() ? QLineF(10, 10, 10, 100) : QLineF(10, 10, 100, 10); return m_data.gContour.GetHeight() >= m_data.gContour.GetWidth() ? QLineF(10, 10, 10, 100) :
QLineF(10, 10, 100, 10);
} }
#endif // VPOSITION_H #endif // VPOSITION_H