Convert all mx and my values to local seam allowance.

--HG--
branch : feature
This commit is contained in:
Roman Telezhynskyi 2016-12-01 20:47:15 +02:00
parent 7b3c05dfa8
commit 939644692d
11 changed files with 376 additions and 36 deletions

View file

@ -520,6 +520,43 @@ void VPattern::customEvent(QEvent *event)
}
}
//---------------------------------------------------------------------------------------------------------------------
VNodeDetail VPattern::ParseDetailNode(const QDomElement &domElement) const
{
const quint32 id = GetParametrUInt(domElement, AttrIdObject, NULL_ID_STR);
const qreal mx = GetParametrDouble(domElement, AttrMx, "0.0");
const qreal my = GetParametrDouble(domElement, AttrMy, "0.0");
const bool reverse = GetParametrUInt(domElement, VAbstractPattern::AttrNodeReverse, "0");
const NodeDetail nodeType = NodeDetail::Contour;
const QString t = GetParametrString(domElement, AttrType, "NodePoint");
Tool tool;
QStringList types = QStringList() << VAbstractPattern::NodePoint
<< VAbstractPattern::NodeArc
<< VAbstractPattern::NodeSpline
<< VAbstractPattern::NodeSplinePath;
switch (types.indexOf(t))
{
case 0: // NodePoint
tool = Tool::NodePoint;
break;
case 1: // NodeArc
tool = Tool::NodeArc;
break;
case 2: // NodeSpline
tool = Tool::NodeSpline;
break;
case 3: // NodeSplinePath
tool = Tool::NodeSplinePath;
break;
default:
VException e(tr("Wrong tag name '%1'.").arg(t));
throw e;
}
return VNodeDetail(id, tool, nodeType, mx, my, reverse);
}
//---------------------------------------------------------------------------------------------------------------------
VPieceNode VPattern::ParseSANode(const QDomElement &domElement) const
{
@ -704,6 +741,8 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
detail.SetInLayout(GetParametrBool(domElement, AttrInLayout, trueStr));
detail.SetUnited(GetParametrBool(domElement, VToolSeamAllowance::AttrUnited, falseStr));
const uint version = GetParametrUInt(domElement, VToolSeamAllowance::AttrVersion, "1");
const QStringList tags = QStringList() << TagNodes
<< TagData
<< TagPatternInfo
@ -719,7 +758,18 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
switch (tags.indexOf(element.tagName()))
{
case 0:// TagNodes
ParseDetailNodes(element, detail);
if (version == 1)
{
// TODO. Delete if minimal supported version is 0.4.0
Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
"Time to refactor the code.");
const bool closed = GetParametrUInt(domElement, AttrClosed, "1");
ParseDetailNodes(element, detail, closed);
}
else
{
ParsePieceNodes(element, detail);
}
break;
case 1:// TagData
break;
@ -818,7 +868,24 @@ void VPattern::ParseDetailElement(const QDomElement &domElement, const Document
}
//---------------------------------------------------------------------------------------------------------------------
void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail) const
void VPattern::ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const
{
QVector<VNodeDetail> oldNodes;
const QDomNodeList nodeList = domElement.childNodes();
for (qint32 i = 0; i < nodeList.size(); ++i)
{
const QDomElement element = nodeList.at(i).toElement();
if (not element.isNull() && element.tagName() == VAbstractPattern::TagNode)
{
oldNodes.append(ParseDetailNode(element));
}
}
detail.GetPath().SetNodes(VNodeDetail::Convert(data, oldNodes, detail.GetSAWidth(), closed));
}
//---------------------------------------------------------------------------------------------------------------------
void VPattern::ParsePieceNodes(const QDomElement &domElement, VPiece &detail) const
{
const QDomNodeList nodeList = domElement.childNodes();
for (qint32 i = 0; i < nodeList.size(); ++i)

View file

@ -114,12 +114,14 @@ private:
VMainGraphicsScene *sceneDraw;
VMainGraphicsScene *sceneDetail;
VNodeDetail ParseDetailNode(const QDomElement &domElement) const;
VPieceNode ParseSANode(const QDomElement &domElement) const;
void ParseDrawElement(const QDomNode& node, const Document &parse);
void ParseDrawMode(const QDomNode& node, const Document &parse, const Draw &mode);
void ParseDetailElement(const QDomElement &domElement, const Document &parse);
void ParseDetailNodes(const QDomElement &domElement, VPiece &detail) const;
void ParseDetailNodes(const QDomElement &domElement, VPiece &detail, bool closed) const;
void ParsePieceNodes(const QDomElement &domElement, VPiece &detail) const;
void ParseDetailCSARecords(const QDomElement &domElement, VPiece &detail) const;
void ParseDetails(const QDomElement &domElement, const Document &parse);

View file

@ -136,6 +136,7 @@ const QString AttrArc = QStringLiteral("arc");
const QString AttrSuffix = QStringLiteral("suffix");
const QString AttrIdObject = QStringLiteral("idObject");
const QString AttrInLayout = QStringLiteral("inLayout");
const QString AttrClosed = QStringLiteral("closed");
const QString TypeLineNone = QStringLiteral("none");
const QString TypeLineLine = QStringLiteral("hair");

View file

@ -137,6 +137,7 @@ extern const QString AttrArc;
extern const QString AttrSuffix;
extern const QString AttrIdObject;
extern const QString AttrInLayout;
extern const QString AttrClosed;
extern const QString TypeLineNone;
extern const QString TypeLineLine;

View file

@ -429,6 +429,8 @@
<xs:attribute name="before" type="xs:double"></xs:attribute>
<xs:attribute name="after" type="xs:double"></xs:attribute>
<xs:attribute name="angle" type="nodeAngle"></xs:attribute>
<xs:attribute name="mx" type="xs:double"></xs:attribute>
<xs:attribute name="my" type="xs:double"></xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>
@ -460,6 +462,7 @@
<xs:attribute name="width" type="xs:double"></xs:attribute>
<xs:attribute name="seamAllowance" type="xs:boolean"></xs:attribute>
<xs:attribute name="united" type="xs:boolean"></xs:attribute>
<xs:attribute name="closed" type="xs:unsignedInt"></xs:attribute>
</xs:complexType>
</xs:element>
</xs:sequence>

View file

@ -1730,8 +1730,6 @@ void VPatternConverter::TagDetailToV0_4_0()
dom.setAttribute(strSeamAllowance, dom.attribute(strSupplement, "0"));
dom.removeAttribute(strSupplement);
dom.removeAttribute(strClosed);
dom.setAttribute(strVersion, "1");
const QStringList tags = QStringList() << strNode << strData << strPatternInfo << strGrainline;
@ -1760,6 +1758,16 @@ void VPatternConverter::TagDetailToV0_4_0()
tagNode.setAttribute(strReverse, element.attribute(strReverse, "0"));
}
if (element.hasAttribute(strMx))
{
tagNode.setAttribute(strMx, element.attribute(strMx, "0"));
}
if (element.hasAttribute(strMy))
{
tagNode.setAttribute(strMy, element.attribute(strMy, "0"));
}
tagNode.setAttribute(strType, element.attribute(strType, ""));
tagNodes.appendChild(tagNode);

View file

@ -28,6 +28,13 @@
#include "vnodedetail.h"
#include "vnodedetail_p.h"
#include "vpiecenode.h"
#include "vpiecepath.h"
#include "../vgeometry/vpointf.h"
#include "../vpatterndb/vcontainer.h"
#include <QLineF>
#include <QVector>
//---------------------------------------------------------------------------------------------------------------------
VNodeDetail::VNodeDetail()
@ -146,3 +153,154 @@ void VNodeDetail::setReverse(bool reverse)
d->reverse = reverse;
}
}
//---------------------------------------------------------------------------------------------------------------------
QVector<VPieceNode> VNodeDetail::Convert(const VContainer *data, const QVector<VNodeDetail> &nodes, qreal width,
bool closed)
{
if (width < 0)
{
width = 0;
}
VPiecePath path;
for (int i = 0; i < nodes.size(); ++i)
{
const VNodeDetail &node = nodes.at(i);
path.Append(VPieceNode(node.getId(), node.getTypeTool(), node.getReverse()));
}
auto LocalWidth = [width](qreal move) noexcept
{
qreal value = width + move;
if (value < 0)
{
value = 0;
}
return value;
};
if (path.PathPoints(data).size() > 2)
{
for (int i = 0; i < nodes.size(); ++i)
{
const VNodeDetail &node = nodes.at(i);
if (node.getTypeTool() == Tool::NodePoint)
{
if (not qFuzzyIsNull(node.getMx()) || not qFuzzyIsNull(node.getMy()))
{
const QPointF previosPoint = path.NodePreviousPoint(data, i);
const QPointF nextPoint = path.NodeNextPoint(data, i);
const QPointF point = data->GeometricObject<VPointF>(node.getId())->toQPointF();
const QPointF xPoint(point.x()+node.getMx(), point.y());
const QPointF yPoint(point.x(), point.y()+node.getMy());
if (IsSABefore(QLineF(point, previosPoint), QLineF(point, xPoint)))
{
path[i].SetSABefore(LocalWidth(node.getMx()));
if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, yPoint)))
{
path[i].SetSAAfter(LocalWidth(node.getMy()));
}
}
else if (IsSABefore(QLineF(point, previosPoint), QLineF(point, yPoint)))
{
path[i].SetSABefore(LocalWidth(node.getMy()));
if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, xPoint)))
{
path[i].SetSAAfter(LocalWidth(node.getMx()));
}
}
else if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, xPoint)))
{
path[i].SetSAAfter(LocalWidth(node.getMx()));
}
else if (IsSAAfter(QLineF(point, nextPoint), QLineF(point, yPoint)))
{
path[i].SetSAAfter(LocalWidth(node.getMy()));
}
}
}
}
}
if (not closed && path.CountNodes() > 1)
{
path[0].SetSABefore(0);
path[path.CountNodes()-1].SetSAAfter(0);
}
return path.GetNodes();
}
//---------------------------------------------------------------------------------------------------------------------
bool VNodeDetail::IsSABefore(const QLineF &saBaseLine, const QLineF &mLine)
{
if (qFuzzyIsNull(mLine.length()))
{
return false;
}
QLineF saLine = saBaseLine;
saLine.setAngle(saLine.angle() - 90);
int saAngle = qRound(saLine.angle());
if (saAngle >= 360)
{
saAngle = 0;
}
int mTest1 = qRound(mLine.angle());
if (mTest1 >= 360)
{
mTest1 = 0;
}
QLineF mrLine = mLine;
mrLine.setAngle(mrLine.angle()+180);
int mTest2 = qRound(mrLine.angle());
if (mTest2 >=360)
{
mTest2 = 0;
}
return (saAngle == mTest1 || saAngle == mTest2);
}
//---------------------------------------------------------------------------------------------------------------------
bool VNodeDetail::IsSAAfter(const QLineF &saBaseLine, const QLineF &mLine)
{
if (qFuzzyIsNull(mLine.length()))
{
return false;
}
QLineF saLine = saBaseLine;
saLine.setAngle(saLine.angle() + 90);
int saAngle = qRound(saLine.angle());
if (saAngle >= 360)
{
saAngle = 0;
}
int mTest1 = qRound(mLine.angle());
if (mTest1 >= 360)
{
mTest1 = 0;
}
QLineF mrLine = mLine;
mrLine.setAngle(mrLine.angle()+180);
int mTest2 = qRound(mrLine.angle());
if (mTest2 >=360)
{
mTest2 = 0;
}
return (saAngle == mTest1 || saAngle == mTest2);
}

View file

@ -37,6 +37,8 @@
#include "../vmisc/def.h"
class VNodeDetailData;
class VPieceNode;
class VContainer;
/**
* @brief The VNodeDetail class keep information about detail node.
@ -122,8 +124,14 @@ public:
bool getReverse() const;
void setReverse(bool reverse);
static QVector<VPieceNode> Convert(const VContainer *data, const QVector<VNodeDetail> &nodes, qreal width,
bool closed);
private:
QSharedDataPointer<VNodeDetailData> d;
static bool IsSABefore(const QLineF &saBaseLine, const QLineF &mLine);
static bool IsSAAfter(const QLineF &saBaseLine, const QLineF &mLine);
};
Q_DECLARE_METATYPE(VNodeDetail)

View file

@ -293,36 +293,10 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, const QVector<VPieceNode
VSAPoint end = VSAPoint(points.last());
if (nodes.size() > 2)
{
if (i == nodes.size() - 1)
{
if (nodes.at(0).GetTypeTool() == Tool::NodePoint)
{
const VPieceNode &node = nodes.at(0);
const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
if (curve->IsPointOnCurve(p))
{
end = VSAPoint(p);
end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
end.SetAngleType(node.GetAngleType());
}
}
}
else
{
if (nodes.at(i+1).GetTypeTool() == Tool::NodePoint)
{
const VPieceNode &node = nodes.at(i+1);
const QPointF p = *data->GeometricObject<VPointF>(node.GetId());
if (curve->IsPointOnCurve(p))
{
end = VSAPoint(p);
end.SetSAAfter(node.GetSAAfter(*data->GetPatternUnit()));
end.SetSABefore(node.GetSABefore(*data->GetPatternUnit()));
end.SetAngleType(node.GetAngleType());
}
}
}
int index = 0;
i == nodes.size() - 1 ? index = 0 : index = i+1;
end = CurvePoint(end, data, nodes.at(index), curve);
}
return end;
}
@ -387,6 +361,107 @@ VSAPoint VPiecePath::EndSegment(const VContainer *data, int i, bool reverse) con
return EndSegment(data, d->m_nodes, i, reverse);
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VPiecePath::NodePreviousPoint(const VContainer *data, int i) const
{
if (i < 0 || i > d->m_nodes.size()-1)
{
return QPointF();
}
if (d->m_nodes.size() > 1)
{
int index = 0;
if (i == 0)
{
index = d->m_nodes.size()-1;
}
else
{
index = i-1;
}
const VPieceNode &node = d->m_nodes.at(index);
switch (node.GetTypeTool())
{
case (Tool::NodePoint):
return *data->GeometricObject<VPointF>(node.GetId());
case (Tool::NodeArc):
case (Tool::NodeSpline):
case (Tool::NodeSplinePath):
{
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
const VSAPoint begin = StartSegment(data, d->m_nodes, i, node.GetReverse());
const VSAPoint end = EndSegment(data, d->m_nodes, i, node.GetReverse());
const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, node.GetReverse());
if (points.size() > 1)
{
return points.at(points.size()-2);
}
}
break;
default:
qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(node.GetTypeTool());
break;
}
}
return QPointF();
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VPiecePath::NodeNextPoint(const VContainer *data, int i) const
{
QPointF point;
if (i < 0 || i > d->m_nodes.size()-1)
{
return point;
}
if (d->m_nodes.size() > 1)
{
int index = 0;
if (i == d->m_nodes.size() - 1)
{
index = 0;
}
else
{
index = i+1;
}
const VPieceNode &node = d->m_nodes.at(index);
switch (node.GetTypeTool())
{
case (Tool::NodePoint):
return *data->GeometricObject<VPointF>(node.GetId());
case (Tool::NodeArc):
case (Tool::NodeSpline):
case (Tool::NodeSplinePath):
{
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(node.GetId());
const VSAPoint begin = StartSegment(data, d->m_nodes, i, node.GetReverse());
const VSAPoint end = EndSegment(data, d->m_nodes, i, node.GetReverse());
const QVector<QPointF> points = curve->GetSegmentPoints(begin, end, node.GetReverse());
if (points.size() > 1)
{
return points.at(1);
}
}
break;
default:
qDebug()<<"Get wrong tool type. Ignore."<< static_cast<char>(node.GetTypeTool());
break;
}
}
return point;
}
//---------------------------------------------------------------------------------------------------------------------
VSAPoint VPiecePath::PreparePointEkv(const VPieceNode &node, const VContainer *data)
{

View file

@ -81,6 +81,9 @@ public:
VSAPoint StartSegment(const VContainer *data, int i, bool reverse) const;
VSAPoint EndSegment(const VContainer *data, int i, bool reverse) const;
QPointF NodePreviousPoint(const VContainer *data, int i) const;
QPointF NodeNextPoint(const VContainer *data, int i) 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);

View file

@ -379,7 +379,21 @@ void VToolSeamAllowance::RefreshDataInFile()
// TODO. Delete if minimal supported version is 0.4.0
Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 4, 0),
"Time to refactor the code.");
doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
const uint version = doc->GetParametrUInt(domElement, VToolSeamAllowance::AttrVersion, "1");
if (version == 1)
{
const VPiece piece = VAbstractTool::data.GetPiece(id);
doc->SetAttribute(domElement, AttrVersion, QString().setNum(pieceVersion));
doc->RemoveAllChildren(domElement);//Very important to clear before rewrite
AddPatternPieceData(doc, domElement, piece);
AddPatternInfo(doc, domElement, piece);
AddGrainline(doc, domElement, piece);
AddNodes(doc, domElement, piece);
AddCSARecords(doc, domElement, piece.GetCustomSARecords());
}
}
}
}