Insert custom seam allowance.

--HG--
branch : feature
This commit is contained in:
Roman Telezhynskyi 2016-11-29 14:10:53 +02:00
parent 5156e0cf25
commit a3843beb0b
6 changed files with 280 additions and 132 deletions

View file

@ -534,28 +534,6 @@ int VGObject::PointInCircle(const QPointF &p, const QPointF &center, qreal radiu
return 2; // inside circle
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief GetReversePoint return revers container of points.
* @param points container with points.
* @return reverced points.
*/
QVector<QPointF> VGObject::GetReversePoints(const QVector<QPointF> &points)
{
if (points.isEmpty())
{
return points;
}
QVector<QPointF> reversePoints(points.size());
qint32 j = 0;
for (qint32 i = points.size() - 1; i >= 0; --i)
{
reversePoints.replace(j, points.at(i));
++j;
}
return reversePoints;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief GetLengthContour return length of contour.

View file

@ -90,7 +90,8 @@ public:
static bool IsPointOnLineSegment (const QPointF &t, const QPointF &p1, const QPointF &p2);
static bool IsPointOnLineviaPDP(const QPointF &t, const QPointF &p1, const QPointF &p2);
static QVector<QPointF> GetReversePoints(const QVector<QPointF> &points);
template <typename T>
static QVector<T> GetReversePoints(const QVector<T> &points);
static int GetLengthContour(const QVector<QPointF> &contour, const QVector<QPointF> &newPoints);
static double accuracyPointOnLine;
@ -105,6 +106,29 @@ private:
static int PointInCircle (const QPointF &p, const QPointF &center, qreal radius);
};
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief GetReversePoint return revers container of points.
* @param points container with points.
* @return reverced points.
*/
template <typename T>
QVector<T> VGObject::GetReversePoints(const QVector<T> &points)
{
if (points.isEmpty())
{
return points;
}
QVector<T> reversePoints(points.size());
qint32 j = 0;
for (qint32 i = points.size() - 1; i >= 0; --i)
{
reversePoints.replace(j, points.at(i));
++j;
}
return reversePoints;
}
Q_DECLARE_TYPEINFO(VGObject, Q_MOVABLE_TYPE);
#endif // VGOBJECT_H

View file

@ -105,6 +105,11 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
return QVector<QPointF>();
}
const QVector<CustomSARecord> records = GetValidRecords();
int recordIndex = -1;
bool insertingCSA = false;
const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
QVector<VSAPoint> pointsEkv;
for (int i = 0; i< d->m_path.CountNodes(); ++i)
{
@ -113,21 +118,54 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
{
case (Tool::NodePoint):
{
const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(node.GetId());
VSAPoint p(point->toQPointF());
if (not insertingCSA)
{
pointsEkv.append(VPiecePath::PreparePointEkv(node, data));
p.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
p.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
p.SetAngleType(node.GetAngleType());
pointsEkv.append(p);
recordIndex = IsCSAStart(records, node.GetId());
if (recordIndex != -1)
{
insertingCSA = true;
const VPiecePath path = data->GetPiecePath(records.at(recordIndex).path);
QVector<VSAPoint> r = path.SeamAllowancePoints(data, width, records.at(recordIndex).reverse);
if (records.at(recordIndex).includeType == PiecePathIncludeType::AsCustomSA)
{
for (int j = 0; j < r.size(); ++j)
{
r[i].SetAngleType(PieceNodeAngle::ByLength);
r[i].SetSABefore(0);
r[i].SetSABefore(0);
}
}
pointsEkv += r;
}
}
else
{
if (records.at(recordIndex).endPoint == node.GetId())
{
insertingCSA = false;
recordIndex = -1;
pointsEkv.append(VPiecePath::PreparePointEkv(node, data));
}
}
}
break;
case (Tool::NodeArc):
case (Tool::NodeSpline):
case (Tool::NodeSplinePath):
{
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
CurveSeamAllowanceSegment(pointsEkv, data, curve, i, node.GetReverse());
if (not insertingCSA)
{
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
pointsEkv += VPiecePath::CurveSeamAllowanceSegment(data, d->m_path.GetNodes(), curve, i,
node.GetReverse(), width);
}
}
break;
default:
@ -136,7 +174,7 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
}
}
return Equidistant(pointsEkv, ToPixel(GetSAWidth(), *data->GetPatternUnit()));
return Equidistant(pointsEkv, width);
}
//---------------------------------------------------------------------------------------------------------------------
@ -287,86 +325,31 @@ QVector<quint32> VPiece::MissingCSAPath(const VPiece &det) const
}
//---------------------------------------------------------------------------------------------------------------------
void VPiece::CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const
QVector<CustomSARecord> VPiece::GetValidRecords() const
{
const VSAPoint begin = d->m_path.StartSegment(data, i, reverse);
const VSAPoint end = d->m_path.EndSegment(data, i, reverse);
const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, reverse);
if (points.isEmpty())
QVector<CustomSARecord> records;
for (int i = 0; i < d->m_customSARecords.size(); ++i)
{
return;
}
const CustomSARecord &record = d->m_customSARecords.at(i);
qreal w1 = begin.GetSAAfter();
qreal w2 = end.GetSABefore();
if (w1 < 0 && w2 < 0)
{// no local widths
for(int i = 0; i < points.size(); ++i)
if (record.startPoint > NULL_ID && record.path > NULL_ID && record.endPoint > NULL_ID)
{
VSAPoint p(points.at(i));
if (i == 0)
{ // first point
p.SetSAAfter(begin.GetSAAfter());
p.SetSABefore(begin.GetSABefore());
p.SetAngleType(begin.GetAngleType());
}
else if (i == points.size() - 1)
{ // last point
p.SetSAAfter(end.GetSAAfter());
p.SetSABefore(end.GetSABefore());
p.SetAngleType(end.GetAngleType());
}
pointsEkv.append(p);
}
}
else
{
const qreal width = ToPixel(GetSAWidth(), *data->GetPatternUnit());
if (w1 < 0)
{
w1 = width;
}
if (w2 < 0)
{
w2 = width;
}
const qreal wDiff = w2 - w1;// Difference between to local widths
const qreal fullLength = VAbstractCurve::PathLength(points);
VSAPoint p(points.at(0));//First point in the list
p.SetSAAfter(begin.GetSAAfter());
p.SetSABefore(begin.GetSABefore());
p.SetAngleType(begin.GetAngleType());
pointsEkv.append(p);
qreal length = 0; // how much we handle
for(int i = 1; i < points.size(); ++i)
{
p = VSAPoint(points.at(i));
if (i == points.size() - 1)
{// last point
p.SetSAAfter(end.GetSAAfter());
p.SetSABefore(end.GetSABefore());
p.SetAngleType(end.GetAngleType());
}
else
{
length += QLineF(points.at(i-1), points.at(i)).length();
const qreal localWidth = w1 + wDiff*(length/fullLength);
p.SetSAAfter(localWidth);
p.SetSABefore(localWidth);
// curve points have angle type by default
}
pointsEkv.append(p);
records.append(record);
}
}
return records;
}
//---------------------------------------------------------------------------------------------------------------------
int VPiece::IsCSAStart(const QVector<CustomSARecord> &records, quint32 id)
{
for (int i = 0; i < records.size(); ++i)
{
if (records.at(i).startPoint == id)
{
return i;
}
}
return -1;
}

View file

@ -84,8 +84,9 @@ public:
private:
QSharedDataPointer<VPieceData> d;
void CurveSeamAllowanceSegment(QVector<VSAPoint> &pointsEkv, const VContainer *data,
const QSharedPointer<VAbstractCurve> &curve, int i, bool reverse) const;
QVector<CustomSARecord> GetValidRecords() const;
static int IsCSAStart(const QVector<CustomSARecord> &records, quint32 id);
};
Q_DECLARE_TYPEINFO(VPiece, Q_MOVABLE_TYPE);

View file

@ -190,6 +190,44 @@ QVector<QPointF> VPiecePath::PathNodePoints(const VContainer *data) const
return points;
}
//---------------------------------------------------------------------------------------------------------------------
QVector<VSAPoint> VPiecePath::SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const
{
SCASSERT(data != nullptr);
QVector<VSAPoint> pointsEkv;
for (int i = 0; i< d->m_nodes.size(); ++i)
{
const VPieceNode &node = d->m_nodes.at(i);
switch (node.GetTypeTool())
{
case (Tool::NodePoint):
{
pointsEkv.append(PreparePointEkv(node, data));
}
break;
case (Tool::NodeArc):
case (Tool::NodeSpline):
case (Tool::NodeSplinePath):
{
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
pointsEkv += CurveSeamAllowanceSegment(data, d->m_nodes, curve, i, node.GetReverse(), width);
}
break;
default:
qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(node.GetTypeTool());
break;
}
}
if (reverse)
{
pointsEkv = VGObject::GetReversePoints(pointsEkv);
}
return pointsEkv;
}
//---------------------------------------------------------------------------------------------------------------------
QPainterPath VPiecePath::PainterPath(const VContainer *data) const
{
@ -210,14 +248,14 @@ QPainterPath VPiecePath::PainterPath(const VContainer *data) const
}
//---------------------------------------------------------------------------------------------------------------------
VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) const
VSAPoint VPiecePath::StartSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse)
{
if (i < 0 && i > CountNodes()-1)
if (i < 0 && i > nodes.size()-1)
{
return VSAPoint();
}
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(nodes.at(i).GetId());
QVector<QPointF> points = curve->GetPoints();
if (reverse)
@ -226,13 +264,13 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) c
}
VSAPoint begin = VSAPoint(points.first());
if (CountNodes() > 1)
if (nodes.size() > 1)
{
if (i == 0)
{
if (at(CountNodes()-1).GetTypeTool() == Tool::NodePoint)
if (nodes.at(nodes.size()-1).GetTypeTool() == Tool::NodePoint)
{
const VPieceNode &node = at(CountNodes()-1);
const VPieceNode &node = nodes.at(nodes.size()-1);
const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
if (curve->IsPointOnCurve(p))
{
@ -245,9 +283,9 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) c
}
else
{
if (at(i-1).GetTypeTool() == Tool::NodePoint)
if (nodes.at(i-1).GetTypeTool() == Tool::NodePoint)
{
const VPieceNode &node = at(i-1);
const VPieceNode &node = nodes.at(i-1);
const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
if (curve->IsPointOnCurve(p))
{
@ -263,14 +301,14 @@ VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) c
}
//---------------------------------------------------------------------------------------------------------------------
VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) const
VSAPoint VPiecePath::EndSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse)
{
if (i < 0 && i > CountNodes()-1)
if (i < 0 && i > nodes.size()-1)
{
return VSAPoint();
}
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(at(i).GetId());
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(nodes.at(i).GetId());
QVector<QPointF> points = curve->GetPoints();
if (reverse)
@ -279,13 +317,13 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) con
}
VSAPoint end = VSAPoint(points.last());
if (CountNodes() > 2)
if (nodes.size() > 2)
{
if (i == CountNodes() - 1)
if (i == nodes.size() - 1)
{
if (at(0).GetTypeTool() == Tool::NodePoint)
if (nodes.at(0).GetTypeTool() == Tool::NodePoint)
{
const VPieceNode &node = at(0);
const VPieceNode &node = nodes.at(0);
const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
if (curve->IsPointOnCurve(p))
{
@ -298,9 +336,9 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) con
}
else
{
if (at(i+1).GetTypeTool() == Tool::NodePoint)
if (nodes.at(i+1).GetTypeTool() == Tool::NodePoint)
{
const VPieceNode &node = at(i+1);
const VPieceNode &node = nodes.at(i+1);
const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
if (curve->IsPointOnCurve(p))
{
@ -362,3 +400,116 @@ int VPiecePath::indexOfNode(quint32 id) const
qDebug()<<"Can't find node.";
return -1;
}
//---------------------------------------------------------------------------------------------------------------------
VSAPoint VPiecePath::StartSegment(const VContainer *data, int i, bool reverse) const
{
return StartSegment(data, d->m_nodes, i, reverse);
}
//---------------------------------------------------------------------------------------------------------------------
VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) const
{
return EndSegment(data, d->m_nodes, i, reverse);
}
//---------------------------------------------------------------------------------------------------------------------
VSAPoint VPiecePath::PreparePointEkv(const VPieceNode &node, const VContainer *data)
{
const QSharedPointer<VPointF> point = data->GeometricObject<VPointF>(node.GetId());
VSAPoint p(point->toQPointF());
p.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
p.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
p.SetAngleType(node.GetAngleType());
return p;
}
//---------------------------------------------------------------------------------------------------------------------
QVector<VSAPoint> VPiecePath::CurveSeamAllowanceSegment(const VContainer *data, const QVector<VPieceNode> &nodes,
const QSharedPointer<VAbstractCurve> &curve, int i,
bool reverse, qreal width)
{
QVector<VSAPoint> pointsEkv;
const VSAPoint begin = StartSegment(data, nodes, i, reverse);
const VSAPoint end = EndSegment(data, nodes, i, reverse);
const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, reverse);
if (points.isEmpty())
{
return pointsEkv;
}
qreal w1 = begin.GetSAAfter();
qreal w2 = end.GetSABefore();
if (w1 < 0 && w2 < 0)
{// no local widths
for(int i = 0; i < points.size(); ++i)
{
VSAPoint p(points.at(i));
if (i == 0)
{ // first point
p.SetSAAfter(begin.GetSAAfter());
p.SetSABefore(begin.GetSABefore());
p.SetAngleType(begin.GetAngleType());
}
else if (i == points.size() - 1)
{ // last point
p.SetSAAfter(end.GetSAAfter());
p.SetSABefore(end.GetSABefore());
p.SetAngleType(end.GetAngleType());
}
pointsEkv.append(p);
}
}
else
{
if (w1 < 0)
{
w1 = width;
}
if (w2 < 0)
{
w2 = width;
}
const qreal wDiff = w2 - w1;// Difference between to local widths
const qreal fullLength = VAbstractCurve::PathLength(points);
VSAPoint p(points.at(0));//First point in the list
p.SetSAAfter(begin.GetSAAfter());
p.SetSABefore(begin.GetSABefore());
p.SetAngleType(begin.GetAngleType());
pointsEkv.append(p);
qreal length = 0; // how much we handle
for(int i = 1; i < points.size(); ++i)
{
p = VSAPoint(points.at(i));
if (i == points.size() - 1)
{// last point
p.SetSAAfter(end.GetSAAfter());
p.SetSABefore(end.GetSABefore());
p.SetAngleType(end.GetAngleType());
}
else
{
length += QLineF(points.at(i-1), points.at(i)).length();
const qreal localWidth = w1 + wDiff*(length/fullLength);
p.SetSAAfter(localWidth);
p.SetSABefore(localWidth);
// curve points have angle type by default
}
pointsEkv.append(p);
}
}
return pointsEkv;
}

View file

@ -40,6 +40,7 @@ class QPointF;
class VContainer;
class VSAPoint;
class QPainterPath;
class VAbstractCurve;
class VPiecePath
{
@ -66,18 +67,28 @@ public:
QString GetName() const;
void SetName(const QString &name);
QVector<QPointF> PathPoints(const VContainer *data) const;
QVector<QPointF> PathNodePoints(const VContainer *data) const;
QVector<QPointF> PathPoints(const VContainer *data) const;
QVector<QPointF> PathNodePoints(const VContainer *data) const;
QVector<VSAPoint> SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const;
QPainterPath PainterPath(const VContainer *data) const;
VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
QVector<quint32> MissingNodes(const VPiecePath &path) const;
int indexOfNode(quint32 id) const;
VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
static VSAPoint StartSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse);
static VSAPoint EndSegment(const VContainer *data, const QVector<VPieceNode> &nodes, int i, bool reverse);
static VSAPoint PreparePointEkv(const VPieceNode &node, const VContainer *data);
static QVector<VSAPoint> CurveSeamAllowanceSegment(const VContainer *data, const QVector<VPieceNode> &nodes,
const QSharedPointer<VAbstractCurve> &curve,
int i, bool reverse, qreal width);
private:
QSharedDataPointer<VPiecePathData> d;
};