mirror of
https://gitlab.com/smart-pattern/valentina.git
synced 2024-09-21 08:14:02 +02:00
645 lines
19 KiB
C++
645 lines
19 KiB
C++
|
/************************************************************************
|
||
|
**
|
||
|
** @file vboundary.cpp
|
||
|
** @author Roman Telezhynskyi <dismine(at)gmail.com>
|
||
|
** @date 24 11, 2023
|
||
|
**
|
||
|
** @brief
|
||
|
** @copyright
|
||
|
** This source code is part of the Valentina project, a pattern making
|
||
|
** program, whose allow create and modeling patterns of clothing.
|
||
|
** Copyright (C) 2023 Valentina project
|
||
|
** <https://gitlab.com/smart-pattern/valentina> All Rights Reserved.
|
||
|
**
|
||
|
** Valentina is free software: you can redistribute it and/or modify
|
||
|
** it under the terms of the GNU General Public License as published by
|
||
|
** the Free Software Foundation, either version 3 of the License, or
|
||
|
** (at your option) any later version.
|
||
|
**
|
||
|
** Valentina is distributed in the hope that it will be useful,
|
||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
** GNU General Public License for more details.
|
||
|
**
|
||
|
** You should have received a copy of the GNU General Public License
|
||
|
** along with Valentina. If not, see <http://www.gnu.org/licenses/>.
|
||
|
**
|
||
|
*************************************************************************/
|
||
|
|
||
|
#include "vboundary.h"
|
||
|
#include "../ifc/exception/vexception.h"
|
||
|
#include "../vgeometry/vgobject.h"
|
||
|
#include "../vmisc/vabstractapplication.h"
|
||
|
#include "vlayoutpiecepath.h"
|
||
|
|
||
|
#include <QPoint>
|
||
|
|
||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 4, 0)
|
||
|
#include "../vmisc/compatibility.h"
|
||
|
#endif
|
||
|
|
||
|
using namespace Qt::Literals::StringLiterals;
|
||
|
|
||
|
namespace
|
||
|
{
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
void FillSequance(VBoundarySequenceItemData itemData, QList<VBoundarySequenceItemData> &sequence)
|
||
|
{
|
||
|
if (itemData.number <= 0)
|
||
|
{
|
||
|
itemData.number = 0;
|
||
|
sequence.append(itemData);
|
||
|
}
|
||
|
else if (sequence.isEmpty())
|
||
|
{
|
||
|
sequence.append(itemData);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
for (int i = 0; i < sequence.size(); ++i)
|
||
|
{
|
||
|
if (sequence.at(i).number > itemData.number || sequence.at(i).number == 0)
|
||
|
{
|
||
|
sequence.insert(i, itemData);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
sequence.append(itemData);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto PrepareSequenceItem(const QVector<VLayoutPoint> &path, bool drawMode, VBoundarySequenceItem type)
|
||
|
-> VBoundarySequenceItemData
|
||
|
{
|
||
|
VLayoutPiecePath countur(path);
|
||
|
countur.SetCutPath(!drawMode);
|
||
|
|
||
|
VBoundarySequenceItemData itemData;
|
||
|
itemData.item = QVariant::fromValue(countur);
|
||
|
itemData.type = type;
|
||
|
|
||
|
return itemData;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto PrepareTPassmarkShape(const VLayoutPassmark &passmark, bool drawMode) -> QVector<QVector<VLayoutPoint>>
|
||
|
{
|
||
|
QVector<VLayoutPoint> shape1;
|
||
|
if (passmark.lines.isEmpty())
|
||
|
{
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
auto TurnPoint = [](QPointF point)
|
||
|
{
|
||
|
VLayoutPoint p(point);
|
||
|
p.SetTurnPoint(true);
|
||
|
return p;
|
||
|
};
|
||
|
|
||
|
QLineF line1 = passmark.lines.constFirst();
|
||
|
shape1.append(TurnPoint(line1.p1()));
|
||
|
shape1.append(TurnPoint(line1.p2()));
|
||
|
|
||
|
if (passmark.lines.size() <= 1)
|
||
|
{
|
||
|
return {shape1};
|
||
|
}
|
||
|
|
||
|
const QLineF &line2 = passmark.lines.constLast();
|
||
|
|
||
|
if (!drawMode)
|
||
|
{
|
||
|
shape1.append(TurnPoint(line2.p1()));
|
||
|
shape1.append(TurnPoint(line2.p2()));
|
||
|
shape1.append(TurnPoint(line1.p2()));
|
||
|
|
||
|
return {shape1};
|
||
|
}
|
||
|
|
||
|
QVector<VLayoutPoint> shape2;
|
||
|
shape2.append(TurnPoint(line2.p1()));
|
||
|
shape2.append(TurnPoint(line2.p2()));
|
||
|
return {shape1, shape2};
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto PrepareNoneBreakingPassmarkShape(const VLayoutPassmark &passmark) -> QVector<QVector<VLayoutPoint>>
|
||
|
{
|
||
|
auto TurnPoint = [](QPointF point)
|
||
|
{
|
||
|
VLayoutPoint p(point);
|
||
|
p.SetTurnPoint(true);
|
||
|
return p;
|
||
|
};
|
||
|
|
||
|
QVector<VLayoutPoint> shape;
|
||
|
shape.reserve(passmark.lines.size() + 1);
|
||
|
for (int i = 0; i < passmark.lines.size(); ++i)
|
||
|
{
|
||
|
const QLineF &line = passmark.lines.at(i);
|
||
|
shape.append(TurnPoint(line.p1()));
|
||
|
|
||
|
if (passmark.lines.size() - 1 == i)
|
||
|
{
|
||
|
shape.append(TurnPoint(line.p2()));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return {shape};
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto PrepareUPassmarkShape(const VLayoutPassmark &passmark) -> QVector<QVector<VLayoutPoint>>
|
||
|
{
|
||
|
auto LayoutPoint = [](QPointF point, bool turnPoint, bool curvePoint)
|
||
|
{
|
||
|
VLayoutPoint p(point);
|
||
|
p.SetTurnPoint(turnPoint);
|
||
|
p.SetCurvePoint(curvePoint);
|
||
|
return p;
|
||
|
};
|
||
|
|
||
|
qreal radius = QLineF(passmark.baseLine.p1(), passmark.lines.constFirst().p1()).length();
|
||
|
|
||
|
if (passmark.baseLine.length() - radius > accuracyPointOnLine)
|
||
|
{
|
||
|
QVector<QLineF> lines = passmark.lines;
|
||
|
if (lines.size() < 3)
|
||
|
{
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
QLineF line1 = lines.takeFirst();
|
||
|
|
||
|
QVector<VLayoutPoint> shape;
|
||
|
shape.reserve(4 + passmark.lines.size() + 1);
|
||
|
|
||
|
shape.append(LayoutPoint(line1.p1(), true, false));
|
||
|
shape.append(LayoutPoint(line1.p2(), true, true));
|
||
|
|
||
|
QLineF line2 = lines.takeLast();
|
||
|
|
||
|
for (int i = 0; i < passmark.lines.size(); ++i)
|
||
|
{
|
||
|
const QLineF &line = passmark.lines.at(i);
|
||
|
shape.append(LayoutPoint(line.p1(), false, true));
|
||
|
|
||
|
if (passmark.lines.size() - 1 == i)
|
||
|
{
|
||
|
shape.append(LayoutPoint(line.p2(), false, true));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
shape.append(LayoutPoint(line2.p1(), true, true));
|
||
|
shape.append(LayoutPoint(line2.p2(), true, false));
|
||
|
|
||
|
return {shape};
|
||
|
}
|
||
|
|
||
|
QVector<VLayoutPoint> shape;
|
||
|
shape.reserve(passmark.lines.size() + 1);
|
||
|
for (int i = 0; i < passmark.lines.size(); ++i)
|
||
|
{
|
||
|
const QLineF &line = passmark.lines.at(i);
|
||
|
shape.append(LayoutPoint(line.p1(), false, true));
|
||
|
|
||
|
if (passmark.lines.size() - 1 == i)
|
||
|
{
|
||
|
shape.append(LayoutPoint(line.p2(), false, true));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!shape.isEmpty())
|
||
|
{
|
||
|
shape.first().SetTurnPoint(true);
|
||
|
shape.last().SetTurnPoint(true);
|
||
|
}
|
||
|
|
||
|
return {shape};
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto PreparePassmarkShape(const VLayoutPassmark &passmark, bool drawMode) -> QVector<QVector<VLayoutPoint>>
|
||
|
{
|
||
|
switch (passmark.type)
|
||
|
{
|
||
|
case PassmarkLineType::OneLine:
|
||
|
case PassmarkLineType::InternalVMark:
|
||
|
case PassmarkLineType::ExternalVMark:
|
||
|
case PassmarkLineType::BoxMark:
|
||
|
case PassmarkLineType::CheckMark:
|
||
|
return PrepareNoneBreakingPassmarkShape(passmark);
|
||
|
break;
|
||
|
case PassmarkLineType::TMark:
|
||
|
return PrepareTPassmarkShape(passmark, drawMode);
|
||
|
break;
|
||
|
case PassmarkLineType::UMark:
|
||
|
return PrepareUPassmarkShape(passmark);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
void ConvertTwoLinesPassmark(const VLayoutPassmark &passmark, QList<VBoundarySequenceItemData> ¬chSequence)
|
||
|
{
|
||
|
if (!passmark.lines.isEmpty())
|
||
|
{
|
||
|
VLayoutPassmark line1 = passmark;
|
||
|
|
||
|
line1.lines = {passmark.lines.constFirst()};
|
||
|
line1.type = PassmarkLineType::OneLine;
|
||
|
line1.baseLine = passmark.lines.constFirst();
|
||
|
|
||
|
VBoundarySequenceItemData itemData;
|
||
|
itemData.item = QVariant::fromValue(line1);
|
||
|
itemData.type = VBoundarySequenceItem::Passmark;
|
||
|
|
||
|
FillSequance(itemData, notchSequence);
|
||
|
}
|
||
|
|
||
|
if (passmark.lines.size() > 1)
|
||
|
{
|
||
|
VLayoutPassmark line2 = passmark;
|
||
|
|
||
|
line2.lines = {passmark.lines.constLast()};
|
||
|
line2.type = PassmarkLineType::OneLine;
|
||
|
line2.baseLine = passmark.lines.constLast();
|
||
|
|
||
|
VBoundarySequenceItemData itemData;
|
||
|
itemData.item = QVariant::fromValue(line2);
|
||
|
itemData.type = VBoundarySequenceItem::Passmark;
|
||
|
|
||
|
FillSequance(itemData, notchSequence);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
void ConvertThreeLinesPassmark(const VLayoutPassmark &passmark, QList<VBoundarySequenceItemData> ¬chSequence)
|
||
|
{
|
||
|
if (!passmark.lines.isEmpty())
|
||
|
{
|
||
|
VLayoutPassmark line1 = passmark;
|
||
|
|
||
|
line1.lines = {passmark.lines.constFirst()};
|
||
|
line1.type = PassmarkLineType::OneLine;
|
||
|
line1.baseLine = passmark.lines.constFirst();
|
||
|
|
||
|
VBoundarySequenceItemData itemData;
|
||
|
itemData.item = QVariant::fromValue(line1);
|
||
|
itemData.type = VBoundarySequenceItem::Passmark;
|
||
|
|
||
|
FillSequance(itemData, notchSequence);
|
||
|
}
|
||
|
|
||
|
if (passmark.lines.size() > 1)
|
||
|
{
|
||
|
VLayoutPassmark line2 = passmark;
|
||
|
|
||
|
line2.lines = {passmark.lines.at(1)};
|
||
|
line2.type = PassmarkLineType::OneLine;
|
||
|
line2.baseLine = passmark.lines.at(1);
|
||
|
|
||
|
VBoundarySequenceItemData itemData;
|
||
|
itemData.item = QVariant::fromValue(line2);
|
||
|
itemData.type = VBoundarySequenceItem::Passmark;
|
||
|
|
||
|
FillSequance(itemData, notchSequence);
|
||
|
}
|
||
|
|
||
|
if (passmark.lines.size() > 2)
|
||
|
{
|
||
|
VLayoutPassmark line3 = passmark;
|
||
|
|
||
|
line3.lines = {passmark.lines.constLast()};
|
||
|
line3.type = PassmarkLineType::OneLine;
|
||
|
line3.baseLine = passmark.lines.constLast();
|
||
|
|
||
|
VBoundarySequenceItemData itemData;
|
||
|
itemData.item = QVariant::fromValue(line3);
|
||
|
itemData.type = VBoundarySequenceItem::Passmark;
|
||
|
|
||
|
FillSequance(itemData, notchSequence);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto SubdividePath(const QVector<VLayoutPoint> &boundary, const QPointF &p, QVector<VLayoutPoint> &sub1,
|
||
|
QVector<VLayoutPoint> &sub2) -> bool
|
||
|
{
|
||
|
if (boundary.size() < 2)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool found = false;
|
||
|
sub1.clear();
|
||
|
sub2.clear();
|
||
|
|
||
|
auto BreakPoint = [p]()
|
||
|
{
|
||
|
VLayoutPoint breakPoint(p);
|
||
|
breakPoint.SetTurnPoint(true);
|
||
|
return breakPoint;
|
||
|
};
|
||
|
|
||
|
for (qint32 i = 0; i < boundary.count() - 1; ++i)
|
||
|
{
|
||
|
if (found)
|
||
|
{
|
||
|
sub2.append(boundary.at(i));
|
||
|
|
||
|
if (i + 1 == boundary.count() - 1)
|
||
|
{
|
||
|
sub2.append(boundary.at(i + 1));
|
||
|
}
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (!VGObject::IsPointOnLineSegment(p, static_cast<QPointF>(boundary.at(i)),
|
||
|
static_cast<QPointF>(boundary.at(i + 1))))
|
||
|
{
|
||
|
sub1.append(boundary.at(i));
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (not VFuzzyComparePoints(boundary.at(i), p))
|
||
|
{
|
||
|
sub1.append(boundary.at(i));
|
||
|
sub1.append(BreakPoint());
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (not sub1.isEmpty())
|
||
|
{
|
||
|
sub1.append(BreakPoint());
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (not VFuzzyComparePoints(boundary.at(i + 1), p))
|
||
|
{
|
||
|
sub2.append(BreakPoint());
|
||
|
|
||
|
if (i + 1 == boundary.count() - 1)
|
||
|
{
|
||
|
sub2.append(boundary.at(i + 1));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
found = true;
|
||
|
}
|
||
|
|
||
|
if (not found)
|
||
|
{
|
||
|
sub1.clear();
|
||
|
}
|
||
|
|
||
|
return found;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto InsertDisconnect(QList<VBoundarySequenceItemData> &sequence, int i, const VBoundarySequenceItemData &item,
|
||
|
bool drawMode) -> bool
|
||
|
{
|
||
|
auto passmark = item.item.value<VLayoutPassmark>();
|
||
|
bool inserted = false;
|
||
|
|
||
|
const auto boundary = sequence.at(i).item.value<VLayoutPiecePath>().Points();
|
||
|
|
||
|
QVector<VLayoutPoint> sub1;
|
||
|
QVector<VLayoutPoint> sub2;
|
||
|
if (!SubdividePath(boundary, passmark.baseLine.p1(), sub1, sub2))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
sequence.removeAt(i);
|
||
|
|
||
|
if (not sub2.isEmpty())
|
||
|
{
|
||
|
sequence.insert(i, PrepareSequenceItem(sub2, drawMode, VBoundarySequenceItem::Boundary));
|
||
|
}
|
||
|
|
||
|
QVector<QVector<VLayoutPoint>> shape = PreparePassmarkShape(passmark, drawMode);
|
||
|
for (auto &subShape : shape)
|
||
|
{
|
||
|
sequence.insert(i, PrepareSequenceItem(subShape, drawMode, VBoundarySequenceItem::PassmarkShape));
|
||
|
}
|
||
|
|
||
|
if (not sub1.isEmpty())
|
||
|
{
|
||
|
sequence.insert(i, PrepareSequenceItem(sub1, drawMode, VBoundarySequenceItem::Boundary));
|
||
|
}
|
||
|
|
||
|
inserted = true;
|
||
|
|
||
|
return inserted;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto InsertCutOut(QList<VBoundarySequenceItemData> &sequence, int i, const VBoundarySequenceItemData &item,
|
||
|
bool drawMode) -> bool
|
||
|
{
|
||
|
auto passmark = item.item.value<VLayoutPassmark>();
|
||
|
|
||
|
QVector<QVector<VLayoutPoint>> shape = PreparePassmarkShape(passmark, drawMode);
|
||
|
if (shape.isEmpty())
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const QVector<VLayoutPoint> &subShape = shape.constFirst();
|
||
|
if (subShape.size() < 2)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
const auto boundary = sequence.at(i).item.value<VLayoutPiecePath>().Points();
|
||
|
|
||
|
QVector<VLayoutPoint> startSub1;
|
||
|
QVector<VLayoutPoint> startSub2;
|
||
|
if (!SubdividePath(boundary, subShape.constFirst(), startSub1, startSub2))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
QVector<VLayoutPoint> endSub1;
|
||
|
QVector<VLayoutPoint> endSub2;
|
||
|
if (!SubdividePath(boundary, subShape.constLast(), endSub1, endSub2))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
sequence.removeAt(i);
|
||
|
|
||
|
if (not endSub2.isEmpty())
|
||
|
{
|
||
|
sequence.insert(i, PrepareSequenceItem(endSub2, drawMode, VBoundarySequenceItem::Boundary));
|
||
|
}
|
||
|
|
||
|
sequence.insert(i, PrepareSequenceItem(subShape, drawMode, VBoundarySequenceItem::PassmarkShape));
|
||
|
|
||
|
if (not startSub1.isEmpty())
|
||
|
{
|
||
|
sequence.insert(i, PrepareSequenceItem(startSub1, drawMode, VBoundarySequenceItem::Boundary));
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
} // namespace
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
VBoundary::VBoundary(const QVector<VLayoutPoint> &boundary, bool seamAllowance, bool builtInSeamAllowance)
|
||
|
: m_boundary(boundary),
|
||
|
m_seamAllowance(seamAllowance),
|
||
|
m_builtInSeamAllowance(builtInSeamAllowance)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto VBoundary::Combine(const QVector<VLayoutPassmark> &passmarks, bool drawMode, bool layoutAllowance) const
|
||
|
-> QList<VBoundarySequenceItemData>
|
||
|
{
|
||
|
QList<VBoundarySequenceItemData> notchSequence;
|
||
|
|
||
|
for (const auto &passmark : passmarks)
|
||
|
{
|
||
|
if (SkipPassmark(passmark, drawMode, layoutAllowance))
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (passmark.type == PassmarkLineType::TwoLines)
|
||
|
{
|
||
|
ConvertTwoLinesPassmark(passmark, notchSequence);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if (passmark.type == PassmarkLineType::ThreeLines)
|
||
|
{
|
||
|
ConvertThreeLinesPassmark(passmark, notchSequence);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
VBoundarySequenceItemData itemData;
|
||
|
itemData.item = QVariant::fromValue(passmark);
|
||
|
itemData.type = VBoundarySequenceItem::Passmark;
|
||
|
|
||
|
FillSequance(itemData, notchSequence);
|
||
|
}
|
||
|
|
||
|
QList<VBoundarySequenceItemData> sequence;
|
||
|
sequence.append(PrepareSequenceItem(m_boundary, drawMode, VBoundarySequenceItem::Boundary));
|
||
|
|
||
|
for (auto &item : notchSequence)
|
||
|
{
|
||
|
if (item.type == VBoundarySequenceItem::Passmark)
|
||
|
{
|
||
|
InsertPassmark(item, sequence, drawMode);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return sequence;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
auto VBoundary::SkipPassmark(const VLayoutPassmark &passmark, bool drawMode, bool layoutAllowance) const -> bool
|
||
|
{
|
||
|
if (m_seamAllowance)
|
||
|
{
|
||
|
if ((m_builtInSeamAllowance && !passmark.isBuiltIn) || (!m_builtInSeamAllowance && passmark.isBuiltIn))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if (!passmark.isBuiltIn)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (layoutAllowance && (passmark.type == PassmarkLineType::ExternalVMark ||
|
||
|
passmark.type == PassmarkLineType::OneLine || passmark.type == PassmarkLineType::TwoLines ||
|
||
|
passmark.type == PassmarkLineType::ThreeLines || passmark.type == PassmarkLineType::TMark))
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
if (!drawMode && passmark.type == PassmarkLineType::ExternalVMark)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
//---------------------------------------------------------------------------------------------------------------------
|
||
|
void VBoundary::InsertPassmark(const VBoundarySequenceItemData &item, QList<VBoundarySequenceItemData> &sequence,
|
||
|
bool drawMode) const
|
||
|
{
|
||
|
auto passmark = item.item.value<VLayoutPassmark>();
|
||
|
|
||
|
bool inserted = false;
|
||
|
for (int i = 0; i < sequence.size(); ++i)
|
||
|
{
|
||
|
const VBoundarySequenceItemData &itemData = sequence.at(i);
|
||
|
if (itemData.type != VBoundarySequenceItem::Boundary)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
switch (passmark.type)
|
||
|
{
|
||
|
case PassmarkLineType::OneLine:
|
||
|
case PassmarkLineType::TMark:
|
||
|
case PassmarkLineType::ExternalVMark:
|
||
|
inserted = InsertDisconnect(sequence, i, item, drawMode);
|
||
|
break;
|
||
|
case PassmarkLineType::UMark:
|
||
|
case PassmarkLineType::InternalVMark:
|
||
|
case PassmarkLineType::BoxMark:
|
||
|
case PassmarkLineType::CheckMark:
|
||
|
inserted = InsertCutOut(sequence, i, item, drawMode);
|
||
|
break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if (inserted)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (not inserted)
|
||
|
{
|
||
|
QString pieceName;
|
||
|
if (!m_pieceName.isEmpty())
|
||
|
{
|
||
|
pieceName = tr("Piece '%1'.").arg(m_pieceName) + ' '_L1;
|
||
|
}
|
||
|
|
||
|
QString errorMsg;
|
||
|
if (!passmark.label.isEmpty())
|
||
|
{
|
||
|
errorMsg = pieceName + tr("Unable to insert notch for point '%1'.").arg(passmark.label);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
errorMsg = pieceName + tr("Unable to insert notch.");
|
||
|
}
|
||
|
|
||
|
VAbstractApplication::VApp()->IsPedantic()
|
||
|
? throw VException(errorMsg)
|
||
|
: qWarning() << VAbstractApplication::warningMessageSignature + errorMsg;
|
||
|
}
|
||
|
}
|