Resolved issue #868. New feature. Connect internal path with cutting contour.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2018-07-26 20:00:24 +03:00
parent 44709728df
commit 8a29755a36
25 changed files with 1399 additions and 85 deletions

View File

@ -53,6 +53,7 @@
- [#862] Force Valentina to immediately terminate if a pattern contains a parsing warning. - [#862] Force Valentina to immediately terminate if a pattern contains a parsing warning.
- [#865] New feature. Dynamic Way to define Material in piece label. - [#865] New feature. Dynamic Way to define Material in piece label.
- [#867] Visibility control for place labels. - [#867] Visibility control for place labels.
- [#868] New feature. Connect internal path with cutting contour.
# Version 0.5.1 (unreleased) # Version 0.5.1 (unreleased)
- [#683] Tool Seam allowance's dialog is off screen on small resolutions. - [#683] Tool Seam allowance's dialog is off screen on small resolutions.

View File

@ -3746,10 +3746,12 @@ void VPattern::ParsePathElement(VMainGraphicsScene *scene, QDomElement &domEleme
initData.path.SetType(static_cast<PiecePathType>(GetParametrUInt(domElement, AttrType, defType))); initData.path.SetType(static_cast<PiecePathType>(GetParametrUInt(domElement, AttrType, defType)));
initData.path.SetName(GetParametrString(domElement, AttrName, tr("Unnamed path"))); initData.path.SetName(GetParametrString(domElement, AttrName, tr("Unnamed path")));
initData.path.SetPenType(LineStyleToPenStyle(GetParametrString(domElement, AttrTypeLine, TypeLineLine))); initData.path.SetPenType(LineStyleToPenStyle(GetParametrString(domElement, AttrTypeLine, TypeLineLine)));
initData.path.SetCutPath(GetParametrBool(domElement, AttrCut, falseStr));
if (initData.path.GetType() == PiecePathType::InternalPath) if (initData.path.GetType() == PiecePathType::InternalPath)
{ {
initData.path.SetCutPath(GetParametrBool(domElement, AttrCut, falseStr));
initData.path.SetFirstToCuttingCountour(GetParametrBool(domElement, AttrFirstToCountour, falseStr));
initData.path.SetLastToCuttingCountour(GetParametrBool(domElement, AttrLastToCountour, falseStr));
initData.path.SetVisibilityTrigger(GetParametrString(domElement, AttrVisible, QChar('1'))); initData.path.SetVisibilityTrigger(GetParametrString(domElement, AttrVisible, QChar('1')));
} }

View File

@ -130,6 +130,8 @@ const QString AttrWidth = QStringLiteral("width");
const QString AttrHeight = QStringLiteral("height"); const QString AttrHeight = QStringLiteral("height");
const QString AttrPlaceLabelType = QStringLiteral("placeLabelType"); const QString AttrPlaceLabelType = QStringLiteral("placeLabelType");
const QString AttrVersion = QStringLiteral("version"); const QString AttrVersion = QStringLiteral("version");
const QString AttrFirstToCountour = QStringLiteral("firstToCountour");
const QString AttrLastToCountour = QStringLiteral("lastToCountour");
const QString TypeLineNone = QStringLiteral("none"); const QString TypeLineNone = QStringLiteral("none");
const QString TypeLineLine = QStringLiteral("hair"); const QString TypeLineLine = QStringLiteral("hair");

View File

@ -151,6 +151,8 @@ extern const QString AttrWidth;
extern const QString AttrHeight; extern const QString AttrHeight;
extern const QString AttrPlaceLabelType; extern const QString AttrPlaceLabelType;
extern const QString AttrVersion; extern const QString AttrVersion;
extern const QString AttrFirstToCountour;
extern const QString AttrLastToCountour;
extern const QString TypeLineNone; extern const QString TypeLineNone;
extern const QString TypeLineLine; extern const QString TypeLineLine;

View File

@ -51,6 +51,7 @@
<file>schema/pattern/v0.7.7.xsd</file> <file>schema/pattern/v0.7.7.xsd</file>
<file>schema/pattern/v0.7.8.xsd</file> <file>schema/pattern/v0.7.8.xsd</file>
<file>schema/pattern/v0.7.9.xsd</file> <file>schema/pattern/v0.7.9.xsd</file>
<file>schema/pattern/v0.7.10.xsd</file>
<file>schema/standard_measurements/v0.3.0.xsd</file> <file>schema/standard_measurements/v0.3.0.xsd</file>
<file>schema/standard_measurements/v0.4.0.xsd</file> <file>schema/standard_measurements/v0.4.0.xsd</file>
<file>schema/standard_measurements/v0.4.1.xsd</file> <file>schema/standard_measurements/v0.4.1.xsd</file>

File diff suppressed because it is too large Load Diff

View File

@ -59,8 +59,8 @@ class QDomElement;
*/ */
const QString VPatternConverter::PatternMinVerStr = QStringLiteral("0.1.0"); const QString VPatternConverter::PatternMinVerStr = QStringLiteral("0.1.0");
const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.7.9"); const QString VPatternConverter::PatternMaxVerStr = QStringLiteral("0.7.10");
const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.7.9.xsd"); const QString VPatternConverter::CurrentSchema = QStringLiteral("://schema/pattern/v0.7.10.xsd");
//VPatternConverter::PatternMinVer; // <== DON'T FORGET TO UPDATE TOO!!!! //VPatternConverter::PatternMinVer; // <== DON'T FORGET TO UPDATE TOO!!!!
//VPatternConverter::PatternMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!! //VPatternConverter::PatternMaxVer; // <== DON'T FORGET TO UPDATE TOO!!!!
@ -229,7 +229,8 @@ QString VPatternConverter::XSDSchema(int ver) const
std::make_pair(0x000706, QStringLiteral("://schema/pattern/v0.7.6.xsd")), std::make_pair(0x000706, QStringLiteral("://schema/pattern/v0.7.6.xsd")),
std::make_pair(0x000707, QStringLiteral("://schema/pattern/v0.7.7.xsd")), std::make_pair(0x000707, QStringLiteral("://schema/pattern/v0.7.7.xsd")),
std::make_pair(0x000708, QStringLiteral("://schema/pattern/v0.7.8.xsd")), std::make_pair(0x000708, QStringLiteral("://schema/pattern/v0.7.8.xsd")),
std::make_pair(0x000709, CurrentSchema) std::make_pair(0x000709, QStringLiteral("://schema/pattern/v0.7.9.xsd")),
std::make_pair(0x00070A, CurrentSchema)
}; };
if (schemas.contains(ver)) if (schemas.contains(ver))
@ -448,6 +449,10 @@ void VPatternConverter::ApplyPatches()
ValidateXML(XSDSchema(0x000709), m_convertedFileName); ValidateXML(XSDSchema(0x000709), m_convertedFileName);
V_FALLTHROUGH V_FALLTHROUGH
case (0x000709): case (0x000709):
ToV0_7_10();
ValidateXML(XSDSchema(0x00070A), m_convertedFileName);
V_FALLTHROUGH
case (0x00070A):
break; break;
default: default:
InvalidVersion(m_ver); InvalidVersion(m_ver);
@ -465,7 +470,7 @@ void VPatternConverter::DowngradeToCurrentMaxVersion()
bool VPatternConverter::IsReadOnly() const bool VPatternConverter::IsReadOnly() const
{ {
// Check if attribute readOnly was not changed in file format // Check if attribute readOnly was not changed in file format
Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == CONVERTER_VERSION_CHECK(0, 7, 9), Q_STATIC_ASSERT_X(VPatternConverter::PatternMaxVer == CONVERTER_VERSION_CHECK(0, 7, 10),
"Check attribute readOnly."); "Check attribute readOnly.");
// Possibly in future attribute readOnly will change position etc. // Possibly in future attribute readOnly will change position etc.
@ -1029,6 +1034,16 @@ void VPatternConverter::ToV0_7_9()
Save(); Save();
} }
//---------------------------------------------------------------------------------------------------------------------
void VPatternConverter::ToV0_7_10()
{
// TODO. Delete if minimal supported version is 0.7.10
Q_STATIC_ASSERT_X(VPatternConverter::PatternMinVer < CONVERTER_VERSION_CHECK(0, 7, 10),
"Time to refactor the code.");
SetVersion(QStringLiteral("0.7.10"));
Save();
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPatternConverter::TagUnitToV0_2_0() void VPatternConverter::TagUnitToV0_2_0()
{ {

View File

@ -53,7 +53,7 @@ public:
static const QString PatternMaxVerStr; static const QString PatternMaxVerStr;
static const QString CurrentSchema; static const QString CurrentSchema;
static Q_DECL_CONSTEXPR const int PatternMinVer = CONVERTER_VERSION_CHECK(0, 1, 0); static Q_DECL_CONSTEXPR const int PatternMinVer = CONVERTER_VERSION_CHECK(0, 1, 0);
static Q_DECL_CONSTEXPR const int PatternMaxVer = CONVERTER_VERSION_CHECK(0, 7, 9); static Q_DECL_CONSTEXPR const int PatternMaxVer = CONVERTER_VERSION_CHECK(0, 7, 10);
protected: protected:
virtual int MinVer() const override; virtual int MinVer() const override;
@ -122,6 +122,7 @@ private:
void ToV0_7_7(); void ToV0_7_7();
void ToV0_7_8(); void ToV0_7_8();
void ToV0_7_9(); void ToV0_7_9();
void ToV0_7_10();
void TagUnitToV0_2_0(); void TagUnitToV0_2_0();
void TagIncrementToV0_2_0(); void TagIncrementToV0_2_0();

View File

@ -327,6 +327,63 @@ QVector<QPointF> VAbstractCurve::CurveIntersectLine(const QVector<QPointF> &poin
return intersections; return intersections;
} }
//---------------------------------------------------------------------------------------------------------------------
bool VAbstractCurve::CurveIntersectAxis(const QPointF &point, qreal angle, const QVector<QPointF> &curvePoints,
QPointF *intersectionPoint)
{
SCASSERT(intersectionPoint != nullptr)
QRectF rec = QRectF(0, 0, INT_MAX, INT_MAX);
rec.translate(-INT_MAX/2.0, -INT_MAX/2.0);
const QLineF axis = VGObject::BuildAxis(point, angle, rec);
const QVector<QPointF> points = VAbstractCurve::CurveIntersectLine(curvePoints, axis);
if (points.size() > 0)
{
if (points.size() == 1)
{
*intersectionPoint = points.at(0);
return true;
}
QMap<qreal, int> forward;
QMap<qreal, int> backward;
for ( qint32 i = 0; i < points.size(); ++i )
{
if (points.at(i) == point)
{ // Always seek unique intersection
continue;
}
const QLineF length(point, points.at(i));
if (qAbs(length.angle()-angle) < 0.1)
{
forward.insert(length.length(), i);
}
else
{
backward.insert(length.length(), i);
}
}
// Closest point is not always want we need. First return point in forward direction if exists.
if (not forward.isEmpty())
{
*intersectionPoint = points.at(forward.first());
return true;
}
else if (not backward.isEmpty())
{
*intersectionPoint = points.at(backward.first());
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QVector<DirectionArrow> VAbstractCurve::DirectionArrows() const QVector<DirectionArrow> VAbstractCurve::DirectionArrows() const
{ {

View File

@ -95,6 +95,8 @@ public:
static qreal PathLength(const QVector<QPointF> &path); static qreal PathLength(const QVector<QPointF> &path);
static QVector<QPointF> CurveIntersectLine(const QVector<QPointF> &points, const QLineF &line); static QVector<QPointF> CurveIntersectLine(const QVector<QPointF> &points, const QLineF &line);
static bool CurveIntersectAxis(const QPointF &point, qreal angle, const QVector<QPointF> &curvePoints,
QPointF *intersectionPoint);
virtual QString NameForHistory(const QString &toolName) const=0; virtual QString NameForHistory(const QString &toolName) const=0;
virtual QVector<DirectionArrow> DirectionArrows() const; virtual QVector<DirectionArrow> DirectionArrows() const;

View File

@ -66,12 +66,13 @@ QVector<VLayoutPiecePath> ConvertInternalPaths(const VPiece &piece, const VConta
QVector<VLayoutPiecePath> paths; QVector<VLayoutPiecePath> paths;
const QVector<quint32> pathsId = piece.GetInternalPaths(); const QVector<quint32> pathsId = piece.GetInternalPaths();
const QVector<QPointF> cuttingPath = piece.CuttingPathPoints(pattern);
for (auto id : pathsId) for (auto id : pathsId)
{ {
const VPiecePath path = pattern->GetPiecePath(id); const VPiecePath path = pattern->GetPiecePath(id);
if (path.GetType() == PiecePathType::InternalPath && path.IsVisible(pattern->DataVariables())) if (path.GetType() == PiecePathType::InternalPath && path.IsVisible(pattern->DataVariables()))
{ {
paths.append(VLayoutPiecePath(path.PathPoints(pattern), path.IsCutPath(), path.GetPenType())); paths.append(VLayoutPiecePath(path.PathPoints(pattern, cuttingPath), path.IsCutPath(), path.GetPenType()));
} }
} }
return paths; return paths;

View File

@ -163,6 +163,22 @@ VPiecePath VContainer::GetPiecePath(quint32 id) const
} }
} }
//---------------------------------------------------------------------------------------------------------------------
quint32 VContainer::GetPieceForPiecePath(quint32 id) const
{
auto i = d->pieces->constBegin();
while (i != d->pieces->constEnd())
{
if (i.value().GetInternalPaths().contains(id))
{
return i.key();
}
++i;
}
return NULL_ID;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief AddGObject add new GObject to container * @brief AddGObject add new GObject to container

View File

@ -136,6 +136,7 @@ public:
static const QSharedPointer<VGObject> GetFakeGObject(quint32 id); static const QSharedPointer<VGObject> GetFakeGObject(quint32 id);
VPiece GetPiece(quint32 id) const; VPiece GetPiece(quint32 id) const;
VPiecePath GetPiecePath(quint32 id) const; VPiecePath GetPiecePath(quint32 id) const;
quint32 GetPieceForPiecePath(quint32 id) const;
template <typename T> template <typename T>
QSharedPointer<T> GetVariable(QString name) const; QSharedPointer<T> GetVariable(QString name) const;
static quint32 getId(); static quint32 getId();

View File

@ -415,6 +415,19 @@ QVector<QPointF> VPiece::SeamAllowancePoints(const VContainer *data) const
return Equidistant(pointsEkv, width); return Equidistant(pointsEkv, width);
} }
//---------------------------------------------------------------------------------------------------------------------
QVector<QPointF> VPiece::CuttingPathPoints(const VContainer *data) const
{
if (IsSeamAllowance() and not IsSeamAllowanceBuiltIn())
{
return SeamAllowancePoints(data);
}
else
{
return MainPathPoints(data);
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QVector<QLineF> VPiece::PassmarksLines(const VContainer *data, const QVector<QPointF> &seamAllowance) const QVector<QLineF> VPiece::PassmarksLines(const VContainer *data, const QVector<QPointF> &seamAllowance) const
{ {

View File

@ -70,6 +70,7 @@ public:
QVector<QPointF> MainPathPoints(const VContainer *data) const; QVector<QPointF> MainPathPoints(const VContainer *data) const;
QVector<VPointF> MainPathNodePoints(const VContainer *data, bool showExcluded = false) const; QVector<VPointF> MainPathNodePoints(const VContainer *data, bool showExcluded = false) const;
QVector<QPointF> SeamAllowancePoints(const VContainer *data) const; QVector<QPointF> SeamAllowancePoints(const VContainer *data) const;
QVector<QPointF> CuttingPathPoints(const VContainer *data) const;
QVector<QLineF> PassmarksLines(const VContainer *data, QVector<QLineF> PassmarksLines(const VContainer *data,
const QVector<QPointF> &seamAllowance = QVector<QPointF>()) const; const QVector<QPointF> &seamAllowance = QVector<QPointF>()) const;
QVector<PlaceLabelImg> PlaceLabelPoints(const VContainer *data) const; QVector<PlaceLabelImg> PlaceLabelPoints(const VContainer *data) const;

View File

@ -32,6 +32,8 @@
#include "../vgeometry/vpointf.h" #include "../vgeometry/vpointf.h"
#include "../vlayout/vabstractpiece.h" #include "../vlayout/vabstractpiece.h"
#include "calculator.h" #include "calculator.h"
#include "../vmisc/vabstractapplication.h"
#include "../ifc/exception/vexceptionobjecterror.h"
#include <QPainterPath> #include <QPainterPath>
@ -142,6 +144,51 @@ QPainterPath MakePainterPath(const QVector<QPointF> &points)
return path; return path;
} }
//---------------------------------------------------------------------------------------------------------------------
qreal FindTipDirection(const QVector<QPointF> &points)
{
if (points.size() <= 1)
{
return 0;
}
const QPointF first = points.first();
for(int i = 1; i < points.size(); ++i)
{
if (first != points.at(i))
{
QLineF line(first, points.at(i));
line.setAngle(line.angle() + 180);
return line.angle();
}
}
return 0;
}
//---------------------------------------------------------------------------------------------------------------------
bool IntersectionWithCuttingCountour(const QVector<QPointF> &cuttingPath, const QVector<QPointF> &points,
QPointF *firstConnection)
{
if (points.size() <= 1)
{
return false;
}
const QPointF first = points.first();
if (VAbstractCurve::IsPointOnCurve(cuttingPath, first))
{ // Point is already part of a cutting countour
*firstConnection = first;
return true;
}
else
{
return VAbstractCurve::CurveIntersectAxis(first, FindTipDirection(points), cuttingPath, firstConnection);
}
}
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -277,7 +324,31 @@ void VPiecePath::SetVisibilityTrigger(const QString &formula)
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QVector<QPointF> VPiecePath::PathPoints(const VContainer *data) const void VPiecePath::SetFirstToCuttingCountour(bool value)
{
d->m_firstToCuttingCountour = value;
}
//---------------------------------------------------------------------------------------------------------------------
bool VPiecePath::IsFirstToCuttingCountour() const
{
return d->m_firstToCuttingCountour;
}
//---------------------------------------------------------------------------------------------------------------------
void VPiecePath::SetLastToCuttingCountour(bool value)
{
d->m_lastToCuttingCountour = value;
}
//---------------------------------------------------------------------------------------------------------------------
bool VPiecePath::IsLastToCuttingCountour() const
{
return d->m_lastToCuttingCountour;
}
//---------------------------------------------------------------------------------------------------------------------
QVector<QPointF> VPiecePath::PathPoints(const VContainer *data, const QVector<QPointF> &cuttingPath) const
{ {
QVector<QPointF> points; QVector<QPointF> points;
for (int i = 0; i < CountNodes(); ++i) for (int i = 0; i < CountNodes(); ++i)
@ -314,6 +385,46 @@ QVector<QPointF> VPiecePath::PathPoints(const VContainer *data) const
} }
} }
if (GetType() == PiecePathType::InternalPath && not cuttingPath.isEmpty() && points.size() > 1)
{
QVector<QPointF> extended = points;
if (IsFirstToCuttingCountour())
{
QPointF firstConnection;
if (IntersectionWithCuttingCountour(cuttingPath, points, &firstConnection))
{
extended.prepend(firstConnection);
}
else
{
const QString errorMsg = QObject::tr("Error in internal path '%1'. There is no intersection of first "
"point with cutting countour")
.arg(GetName());
qApp->IsPedantic() ? throw VExceptionObjectError(errorMsg) : qWarning() << errorMsg;
}
}
if (IsLastToCuttingCountour())
{
QPointF lastConnection;
if (IntersectionWithCuttingCountour(cuttingPath, VGObject::GetReversePoints(points),
&lastConnection))
{
extended.append(lastConnection);
}
else
{
const QString errorMsg = QObject::tr("Error in internal path '%1'. There is no intersection of last "
"point with cutting countour")
.arg(GetName());
qApp->IsPedantic() ? throw VExceptionObjectError(errorMsg) : qWarning() << errorMsg;
}
}
points = extended;
}
return points; return points;
} }
@ -421,9 +532,9 @@ QVector<VSAPoint> VPiecePath::SeamAllowancePoints(const VContainer *data, qreal
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QPainterPath VPiecePath::PainterPath(const VContainer *data) const QPainterPath VPiecePath::PainterPath(const VContainer *data, const QVector<QPointF> &cuttingPath) const
{ {
return MakePainterPath(PathPoints(data)); return MakePainterPath(PathPoints(data, cuttingPath));
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -85,12 +85,19 @@ public:
QString GetVisibilityTrigger() const; QString GetVisibilityTrigger() const;
void SetVisibilityTrigger(const QString &formula); void SetVisibilityTrigger(const QString &formula);
QVector<QPointF> PathPoints(const VContainer *data) const; void SetFirstToCuttingCountour(bool value);
bool IsFirstToCuttingCountour() const;
void SetLastToCuttingCountour(bool value);
bool IsLastToCuttingCountour() const;
QVector<QPointF> PathPoints(const VContainer *data,
const QVector<QPointF> &cuttingPath = QVector<QPointF>()) const;
QVector<VPointF> PathNodePoints(const VContainer *data, bool showExcluded = true) const; QVector<VPointF> PathNodePoints(const VContainer *data, bool showExcluded = true) const;
QVector<QVector<QPointF> > PathCurvePoints(const VContainer *data) const; QVector<QVector<QPointF> > PathCurvePoints(const VContainer *data) const;
QVector<VSAPoint> SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const; QVector<VSAPoint> SeamAllowancePoints(const VContainer *data, qreal width, bool reverse) const;
QPainterPath PainterPath(const VContainer *data) const; QPainterPath PainterPath(const VContainer *data, const QVector<QPointF> &cuttingPath) const;
QVector<QPainterPath> CurvesPainterPath(const VContainer *data) const; QVector<QPainterPath> CurvesPainterPath(const VContainer *data) const;
QList<quint32> Dependencies() const; QList<quint32> Dependencies() const;

View File

@ -48,7 +48,9 @@ public:
m_name(), m_name(),
m_penType(Qt::SolidLine), m_penType(Qt::SolidLine),
m_cut(false), m_cut(false),
m_visibilityTrigger('1') m_visibilityTrigger('1'),
m_firstToCuttingCountour(false),
m_lastToCuttingCountour(false)
{} {}
explicit VPiecePathData(PiecePathType type) explicit VPiecePathData(PiecePathType type)
@ -57,7 +59,9 @@ public:
m_name(), m_name(),
m_penType(Qt::SolidLine), m_penType(Qt::SolidLine),
m_cut(false), m_cut(false),
m_visibilityTrigger('1') m_visibilityTrigger('1'),
m_firstToCuttingCountour(false),
m_lastToCuttingCountour(false)
{} {}
VPiecePathData(const VPiecePathData &path) VPiecePathData(const VPiecePathData &path)
@ -67,7 +71,9 @@ public:
m_name(path.m_name), m_name(path.m_name),
m_penType(path.m_penType), m_penType(path.m_penType),
m_cut(path.m_cut), m_cut(path.m_cut),
m_visibilityTrigger(path.m_visibilityTrigger) m_visibilityTrigger(path.m_visibilityTrigger),
m_firstToCuttingCountour(path.m_firstToCuttingCountour),
m_lastToCuttingCountour(path.m_lastToCuttingCountour)
{} {}
~VPiecePathData(); ~VPiecePathData();
@ -78,6 +84,8 @@ public:
Qt::PenStyle m_penType; Qt::PenStyle m_penType;
bool m_cut; bool m_cut;
QString m_visibilityTrigger; QString m_visibilityTrigger;
bool m_firstToCuttingCountour;
bool m_lastToCuttingCountour;
private: private:
VPiecePathData &operator=(const VPiecePathData &) Q_DECL_EQ_DELETE; VPiecePathData &operator=(const VPiecePathData &) Q_DECL_EQ_DELETE;

View File

@ -37,6 +37,21 @@
#include <QMenu> #include <QMenu>
#include <QTimer> #include <QTimer>
namespace
{
QVector<QPointF> CuttingPath(quint32 id, const VContainer *data)
{
QVector<QPointF> path;
const quint32 pieceId = data->GetPieceForPiecePath(id);
if (pieceId > NULL_ID)
{
path = data->GetPiece(pieceId).CuttingPathPoints(data);
}
return path;
}
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget *parent) DialogPiecePath::DialogPiecePath(const VContainer *data, quint32 toolId, QWidget *parent)
: DialogTool(data, toolId, parent), : DialogTool(data, toolId, parent),
@ -151,6 +166,7 @@ void DialogPiecePath::ChosenObject(quint32 id, const SceneObject &type)
SCASSERT(visPath != nullptr); SCASSERT(visPath != nullptr);
const VPiecePath p = CreatePath(); const VPiecePath p = CreatePath();
visPath->SetPath(p); visPath->SetPath(p);
visPath->SetCuttingPath(CuttingPath(toolId, data));
if (p.CountNodes() == 1) if (p.CountNodes() == 1)
{ {
@ -347,6 +363,7 @@ void DialogPiecePath::ListChanged()
auto visPath = qobject_cast<VisToolPiecePath *>(vis); auto visPath = qobject_cast<VisToolPiecePath *>(vis);
SCASSERT(visPath != nullptr); SCASSERT(visPath != nullptr);
visPath->SetPath(CreatePath()); visPath->SetPath(CreatePath());
visPath->SetCuttingPath(CuttingPath(toolId, data));
visPath->RefreshGeometry(); visPath->RefreshGeometry();
} }
@ -882,9 +899,12 @@ void DialogPiecePath::InitPathTab()
InitPathTypes(); InitPathTypes();
connect(ui->comboBoxType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this]() connect(ui->comboBoxType, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [this]()
{ {
ui->comboBoxPenType->setEnabled(GetType() == PiecePathType::InternalPath); const bool isInternalPath = GetType() == PiecePathType::InternalPath;
ui->checkBoxCut->setEnabled(GetType() == PiecePathType::InternalPath); ui->comboBoxPenType->setEnabled(isInternalPath);
ui->tabControl->setEnabled(GetType() == PiecePathType::InternalPath); ui->checkBoxCut->setEnabled(isInternalPath);
ui->tabControl->setEnabled(isInternalPath);
ui->checkBoxFirstPointToCuttingContour->setEnabled(isInternalPath);
ui->checkBoxLastPointToCuttingContour->setEnabled(isInternalPath);
ValidObjects(PathIsValid()); ValidObjects(PathIsValid());
}); });
@ -1092,8 +1112,12 @@ void DialogPiecePath::SetPiecePath(const VPiecePath &path)
VisToolPiecePath *visPath = qobject_cast<VisToolPiecePath *>(vis); VisToolPiecePath *visPath = qobject_cast<VisToolPiecePath *>(vis);
SCASSERT(visPath != nullptr); SCASSERT(visPath != nullptr);
visPath->SetPath(path); visPath->SetPath(path);
visPath->SetCuttingPath(CuttingPath(toolId, data));
SetPenType(path.GetPenType()); SetPenType(path.GetPenType());
SetCutPath(path.IsCutPath()); SetCutPath(path.IsCutPath());
ui->checkBoxFirstPointToCuttingContour->setChecked(path.IsFirstToCuttingCountour());
ui->checkBoxLastPointToCuttingContour->setChecked(path.IsLastToCuttingCountour());
if (path.GetType() == PiecePathType::InternalPath) if (path.GetType() == PiecePathType::InternalPath)
{ {
@ -1126,6 +1150,8 @@ void DialogPiecePath::SetType(PiecePathType type)
ui->comboBoxPenType->setEnabled(type == PiecePathType::InternalPath); ui->comboBoxPenType->setEnabled(type == PiecePathType::InternalPath);
ui->checkBoxCut->setEnabled(type == PiecePathType::InternalPath); ui->checkBoxCut->setEnabled(type == PiecePathType::InternalPath);
ui->checkBoxFirstPointToCuttingContour->setEnabled(type == PiecePathType::InternalPath);
ui->checkBoxLastPointToCuttingContour->setEnabled(type == PiecePathType::InternalPath);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -1250,6 +1276,7 @@ void DialogPiecePath::SetFormulaSAWidth(const QString &formula)
VisToolPiecePath *path = qobject_cast<VisToolPiecePath *>(vis); VisToolPiecePath *path = qobject_cast<VisToolPiecePath *>(vis);
SCASSERT(path != nullptr) SCASSERT(path != nullptr)
path->SetPath(CreatePath()); path->SetPath(CreatePath());
path->SetCuttingPath(CuttingPath(toolId, data));
if (ui->tabWidget->indexOf(ui->tabSeamAllowance) == -1) if (ui->tabWidget->indexOf(ui->tabSeamAllowance) == -1)
{ {
@ -1314,19 +1341,14 @@ VPiecePath DialogPiecePath::CreatePath() const
path.Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole))); path.Append(qvariant_cast<VPieceNode>(item->data(Qt::UserRole)));
} }
const bool isInternalPath = (GetType() == PiecePathType::InternalPath);
path.SetType(GetType()); path.SetType(GetType());
path.SetName(ui->lineEditName->text()); path.SetName(ui->lineEditName->text());
path.SetPenType(GetType() == PiecePathType::InternalPath ? GetPenType() : Qt::SolidLine); path.SetPenType(isInternalPath ? GetPenType() : Qt::SolidLine);
path.SetCutPath(GetType() == PiecePathType::InternalPath ? IsCutPath() : false); path.SetCutPath(isInternalPath ? IsCutPath() : false);
path.SetFirstToCuttingCountour(isInternalPath ? ui->checkBoxFirstPointToCuttingContour->isChecked() : false);
if (GetType() == PiecePathType::InternalPath) path.SetLastToCuttingCountour(isInternalPath ? ui->checkBoxLastPointToCuttingContour->isChecked() : false);
{ path.SetVisibilityTrigger(isInternalPath ? GetFormulaVisible() : QChar('1'));
path.SetVisibilityTrigger(GetFormulaVisible());
}
else
{
path.SetVisibilityTrigger(QChar('1'));
}
return path; return path;
} }

View File

@ -95,6 +95,20 @@
</item> </item>
</layout> </layout>
</item> </item>
<item>
<widget class="QCheckBox" name="checkBoxFirstPointToCuttingContour">
<property name="text">
<string>Continue the first point to the cutting contour</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="checkBoxLastPointToCuttingContour">
<property name="text">
<string>Continue the last point to the cutting contour</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QListWidget" name="listWidget"> <widget class="QListWidget" name="listWidget">
<property name="dragDropMode"> <property name="dragDropMode">
@ -1403,7 +1417,7 @@
</connection> </connection>
</connections> </connections>
<buttongroups> <buttongroups>
<buttongroup name="buttonGroupAngleType"/>
<buttongroup name="buttonGroupMarkType"/> <buttongroup name="buttonGroupMarkType"/>
<buttongroup name="buttonGroupAngleType"/>
</buttongroups> </buttongroups>
</ui> </ui>

View File

@ -190,57 +190,7 @@ VToolCurveIntersectAxis *VToolCurveIntersectAxis::Create(VToolCurveIntersectAxis
bool VToolCurveIntersectAxis::FindPoint(const QPointF &point, qreal angle, const QVector<QPointF> &curvePoints, bool VToolCurveIntersectAxis::FindPoint(const QPointF &point, qreal angle, const QVector<QPointF> &curvePoints,
QPointF *intersectionPoint) QPointF *intersectionPoint)
{ {
SCASSERT(intersectionPoint != nullptr) return VAbstractCurve::CurveIntersectAxis(point, angle, curvePoints, intersectionPoint);
QRectF rec = QRectF(0, 0, INT_MAX, INT_MAX);
rec.translate(-INT_MAX/2.0, -INT_MAX/2.0);
const QLineF axis = VGObject::BuildAxis(point, angle, rec);
const QVector<QPointF> points = VAbstractCurve::CurveIntersectLine(curvePoints, axis);
if (points.size() > 0)
{
if (points.size() == 1)
{
*intersectionPoint = points.at(0);
return true;
}
QMap<qreal, int> forward;
QMap<qreal, int> backward;
for ( qint32 i = 0; i < points.size(); ++i )
{
if (points.at(i) == point)
{ // Always seek unique intersection
continue;
}
const QLineF length(point, points.at(i));
if (qAbs(length.angle()-angle) < 0.1)
{
forward.insert(length.length(), i);
}
else
{
backward.insert(length.length(), i);
}
}
// Closest point is not always want we need. First return point in forward direction if exists.
if (not forward.isEmpty())
{
*intersectionPoint = points.at(forward.first());
return true;
}
else if (not backward.isEmpty())
{
*intersectionPoint = points.at(backward.first());
return true;
}
}
return false;
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -32,6 +32,7 @@
#include "../vpatterndb/vpiecenode.h" #include "../vpatterndb/vpiecenode.h"
#include "../../undocommands/savepieceoptions.h" #include "../../undocommands/savepieceoptions.h"
#include "../vtoolseamallowance.h" #include "../vtoolseamallowance.h"
#include "../ifc/xml/vabstractpattern.h"
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
VToolPiecePath *VToolPiecePath::Create(const QPointer<DialogTool> &dialog, VMainGraphicsScene *scene, VToolPiecePath *VToolPiecePath::Create(const QPointer<DialogTool> &dialog, VMainGraphicsScene *scene,
@ -194,6 +195,8 @@ void VToolPiecePath::AddAttributes(VAbstractPattern *doc, QDomElement &domElemen
{ {
doc->SetAttribute(domElement, VAbstractPattern::AttrVisible, path.GetVisibilityTrigger()); doc->SetAttribute(domElement, VAbstractPattern::AttrVisible, path.GetVisibilityTrigger());
doc->SetAttribute(domElement, AttrCut, path.IsCutPath()); doc->SetAttribute(domElement, AttrCut, path.IsCutPath());
doc->SetAttribute(domElement, AttrFirstToCountour, path.IsFirstToCuttingCountour());
doc->SetAttribute(domElement, AttrLastToCountour, path.IsLastToCuttingCountour());
} }
} }
@ -302,7 +305,16 @@ void VToolPiecePath::RefreshGeometry()
const VPiecePath path = VAbstractTool::data.GetPiecePath(m_id); const VPiecePath path = VAbstractTool::data.GetPiecePath(m_id);
if (path.GetType() == PiecePathType::InternalPath) if (path.GetType() == PiecePathType::InternalPath)
{ {
QPainterPath p = path.PainterPath(this->getData()); QVector<QPointF> cuttingPath;
const quint32 pieceId = VAbstractTool::data.GetPieceForPiecePath(m_id);
if (pieceId > NULL_ID)
{
VPiece piece = VAbstractTool::data.GetPiece(pieceId);
// We cannot use current VContainer because it doesn't have current seam allowance value
const VContainer pData = VAbstractPattern::getTool(pieceId)->getData();
cuttingPath = piece.CuttingPathPoints(&pData);
}
QPainterPath p = path.PainterPath(this->getData(), cuttingPath);
p.setFillRule(Qt::OddEvenFill); p.setFillRule(Qt::OddEvenFill);
this->setPath(p); this->setPath(p);

View File

@ -145,6 +145,7 @@ VToolSeamAllowance *VToolSeamAllowance::Create(VToolSeamAllowanceInitData &initD
initData.scene->addItem(piece); initData.scene->addItem(piece);
VMainGraphicsView::NewSceneRect(initData.scene, qApp->getSceneView(), piece); VMainGraphicsView::NewSceneRect(initData.scene, qApp->getSceneView(), piece);
VAbstractPattern::AddTool(initData.id, piece); VAbstractPattern::AddTool(initData.id, piece);
piece->RefreshGeometry(true); // Refresh internal paths
} }
//Very important to delete it. Only this tool need this special variable. //Very important to delete it. Only this tool need this special variable.
initData.data->RemoveVariable(currentSeamAllowance); initData.data->RemoveVariable(currentSeamAllowance);
@ -1297,7 +1298,6 @@ VToolSeamAllowance::VToolSeamAllowance(const VToolSeamAllowanceInitData &initDat
AllowSelecting(true); AllowSelecting(true);
EnableToolMove(true); EnableToolMove(true);
AllowHover(true); AllowHover(true);
RefreshGeometry();
this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus this->setFlag(QGraphicsItem::ItemIsFocusable, true);// For keyboard input focus

View File

@ -38,7 +38,8 @@ VisToolPiecePath::VisToolPiecePath(const VContainer *data, QGraphicsItem *parent
: VisPath(data, parent), : VisPath(data, parent),
m_points(), m_points(),
m_line(nullptr), m_line(nullptr),
m_path() m_path(),
m_cuttingPath()
{ {
m_line = InitItem<VScaledLine>(supportColor, this); m_line = InitItem<VScaledLine>(supportColor, this);
} }
@ -50,7 +51,8 @@ void VisToolPiecePath::RefreshGeometry()
if (m_path.CountNodes() > 0) if (m_path.CountNodes() > 0)
{ {
DrawPath(this, m_path.PainterPath(Visualization::data), mainColor, m_path.GetPenType(), Qt::RoundCap); DrawPath(this, m_path.PainterPath(Visualization::data, m_cuttingPath), mainColor, m_path.GetPenType(),
Qt::RoundCap);
const QVector<VPointF> nodes = m_path.PathNodePoints(Visualization::data); const QVector<VPointF> nodes = m_path.PathNodePoints(Visualization::data);
@ -79,6 +81,12 @@ void VisToolPiecePath::SetPath(const VPiecePath &path)
m_path = path; m_path = path;
} }
//---------------------------------------------------------------------------------------------------------------------
void VisToolPiecePath::SetCuttingPath(const QVector<QPointF> &cuttingPath)
{
m_cuttingPath = cuttingPath;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VisToolPiecePath::mousePressEvent(QGraphicsSceneMouseEvent *event) void VisToolPiecePath::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {

View File

@ -46,6 +46,7 @@ public:
virtual void RefreshGeometry() override; virtual void RefreshGeometry() override;
void SetPath(const VPiecePath &path); void SetPath(const VPiecePath &path);
void SetCuttingPath(const QVector<QPointF> &cuttingPath);
virtual int type() const override {return Type;} virtual int type() const override {return Type;}
enum { Type = UserType + static_cast<int>(Vis::ToolPiecePath)}; enum { Type = UserType + static_cast<int>(Vis::ToolPiecePath)};
protected: protected:
@ -59,6 +60,8 @@ private:
VPiecePath m_path; VPiecePath m_path;
QVector<QPointF> m_cuttingPath;
VSimplePoint *GetPoint(quint32 i, const QColor &color); VSimplePoint *GetPoint(quint32 i, const QColor &color);
void HideAllItems(); void HideAllItems();