From 9effd8af02cdbbe59c25d557e31201bd4a4b2638 Mon Sep 17 00:00:00 2001 From: dismine Date: Wed, 7 Jan 2015 18:54:43 +0200 Subject: [PATCH] Layout detail. --HG-- branch : feature --- src/app/geometry/geometry.pri | 2 - src/app/geometry/vdetail.cpp | 44 +++ src/app/geometry/vdetail.h | 3 + src/app/geometry/vequidistant.cpp | 445 --------------------------- src/app/geometry/vequidistant.h | 113 ------- src/app/mainwindow.cpp | 13 +- src/app/mainwindow.h | 5 +- src/app/options.h | 1 - src/app/tablewindow.cpp | 174 +++++------ src/app/tablewindow.h | 8 +- src/app/tools/vtooldetail.cpp | 5 +- src/libs/vlayout/vabstractdetail.cpp | 295 ++++++++++++++++++ src/libs/vlayout/vabstractdetail.h | 13 + src/libs/vlayout/vlayout.pri | 4 +- src/libs/vlayout/vlayout.pro | 3 - src/libs/vlayout/vlayoutdef.h | 34 ++ src/libs/vlayout/vlayoutdetail.cpp | 139 +++++++++ src/libs/vlayout/vlayoutdetail.h | 38 ++- src/libs/vlayout/vlayoutdetail_p.h | 77 +++++ 19 files changed, 750 insertions(+), 666 deletions(-) delete mode 100644 src/app/geometry/vequidistant.cpp delete mode 100644 src/app/geometry/vequidistant.h create mode 100644 src/libs/vlayout/vlayoutdef.h create mode 100644 src/libs/vlayout/vlayoutdetail_p.h diff --git a/src/app/geometry/geometry.pri b/src/app/geometry/geometry.pri index 708385de8..9c8bf58c9 100644 --- a/src/app/geometry/geometry.pri +++ b/src/app/geometry/geometry.pri @@ -10,7 +10,6 @@ HEADERS += \ $$PWD/varc.h \ $$PWD/vgobject.h \ $$PWD/vpointf.h \ - $$PWD/vequidistant.h \ $$PWD/vabstractcurve.h \ $$PWD/vnodedetail_p.h \ $$PWD/vdetail_p.h \ @@ -30,5 +29,4 @@ SOURCES += \ $$PWD/varc.cpp \ $$PWD/vgobject.cpp \ $$PWD/vpointf.cpp \ - $$PWD/vequidistant.cpp \ $$PWD/vabstractcurve.cpp diff --git a/src/app/geometry/vdetail.cpp b/src/app/geometry/vdetail.cpp index edc286def..c1ce9a6fe 100644 --- a/src/app/geometry/vdetail.cpp +++ b/src/app/geometry/vdetail.cpp @@ -30,6 +30,7 @@ #include "vdetail_p.h" #include "../container/vcontainer.h" #include "vpointf.h" +#include "../core/vapplication.h" #include #include @@ -434,6 +435,49 @@ QVector VDetail::SeamAllowancePoints(const VContainer *data) const return pointsEkv; } +//--------------------------------------------------------------------------------------------------------------------- +QPainterPath VDetail::ContourPath(const VContainer *data) const +{ + QVector points = ContourPoints(data); + QVector pointsEkv = SeamAllowancePoints(data); + + QPainterPath path; + + // contour + path.moveTo(points[0]); + for (qint32 i = 1; i < points.count(); ++i) + { + path.lineTo(points.at(i)); + } + path.lineTo(points.at(0)); + + // seam allowence + if (getSeamAllowance() == true) + { + QPainterPath ekv; + QVector p; + if (getClosed() == true) + { + p = Equidistant(pointsEkv, EquidistantType::CloseEquidistant, qApp->toPixel(getWidth())); + } + else + { + p = Equidistant(pointsEkv, EquidistantType::OpenEquidistant, qApp->toPixel(getWidth())); + } + + ekv.moveTo(p.at(0)); + for (qint32 i = 1; i < p.count(); ++i) + { + ekv.lineTo(p.at(i)); + } + + path.addPath(ekv); + path.setFillRule(Qt::WindingFill); + } + + return path; +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief listNodePoint return list nodes only with points. diff --git a/src/app/geometry/vdetail.h b/src/app/geometry/vdetail.h index 366f7afaa..8100248e4 100644 --- a/src/app/geometry/vdetail.h +++ b/src/app/geometry/vdetail.h @@ -36,6 +36,7 @@ class VDetailData; class VContainer; +class QPainterPath; /** * @brief The VDetail class for path of object (points, arcs, splines). @@ -79,6 +80,8 @@ public: QVector ContourPoints(const VContainer *data) const; QVector SeamAllowancePoints(const VContainer *data) const; + + QPainterPath ContourPath(const VContainer *data) const; private: QSharedDataPointer d; diff --git a/src/app/geometry/vequidistant.cpp b/src/app/geometry/vequidistant.cpp deleted file mode 100644 index 6593e54dd..000000000 --- a/src/app/geometry/vequidistant.cpp +++ /dev/null @@ -1,445 +0,0 @@ -/************************************************************************ - ** - ** @file vequidistant.cpp - ** @author Roman Telezhynskyi - ** @date 28 1, 2014 - ** - ** @brief - ** @copyright - ** This source code is part of the Valentine project, a pattern making - ** program, whose allow create and modeling patterns of clothing. - ** Copyright (C) 2013 Valentina project - ** 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 . - ** - *************************************************************************/ - -#include "varc.h" -#include "vequidistant.h" -#include "vpointf.h" -#include "vspline.h" -#include "vsplinepath.h" -#include "../core/vapplication.h" -#include -#include -#include "../container/vcontainer.h" -#include - -//--------------------------------------------------------------------------------------------------------------------- -VEquidistant::VEquidistant(const VContainer *data) - :data(data) -{ - SCASSERT(data != nullptr); -} - -//--------------------------------------------------------------------------------------------------------------------- -QPainterPath VEquidistant::ContourPath(const quint32 &idDetail) const -{ - SCASSERT(data != nullptr); - VDetail detail = data->GetDetail(idDetail); - QVector points; - QVector pointsEkv; - for (int i = 0; i< detail.CountNode(); ++i) - { - switch (detail.at(i).getTypeTool()) - { - case (Tool::NodePoint): - { - const QSharedPointer point = data->GeometricObject(detail.at(i).getId()); - points.append(point->toQPointF()); - if (detail.getSeamAllowance() == true) - { - QPointF pEkv = point->toQPointF(); - pEkv.setX(pEkv.x()+detail.at(i).getMx()); - pEkv.setY(pEkv.y()+detail.at(i).getMy()); - pointsEkv.append(pEkv); - } - } - break; - case (Tool::NodeArc): - case (Tool::NodeSpline): - case (Tool::NodeSplinePath): - { - const QSharedPointer curve=data->GeometricObject(detail.at(i).getId()); - - const QPointF begin = StartSegment(detail, i); - const QPointF end = EndSegment(detail, i); - - QVector nodePoints = curve->GetSegmentPoints(begin, end, detail.at(i).getReverse()); - points << nodePoints; - if (detail.getSeamAllowance() == true) - { - pointsEkv << biasPoints(nodePoints, detail.at(i).getMx(), detail.at(i).getMy()); - } - } - break; - default: - qDebug()<<"Get wrong tool type. Ignore."<< static_cast(detail.at(i).getTypeTool()); - break; - } - } - - QPainterPath path; - path.moveTo(points[0]); - for (qint32 i = 1; i < points.count(); ++i) - { - path.lineTo(points.at(i)); - } - path.lineTo(points.at(0)); - - pointsEkv = CorrectEquidistantPoints(pointsEkv); - pointsEkv = CheckLoops(pointsEkv); - - if (detail.getSeamAllowance() == true) - { - QPainterPath ekv; - if (detail.getClosed() == true) - { - ekv = Equidistant(pointsEkv, EquidistantType::CloseEquidistant, qApp->toPixel(detail.getWidth())); - } - else - { - ekv = Equidistant(pointsEkv, EquidistantType::OpenEquidistant, qApp->toPixel(detail.getWidth())); - } - path.addPath(ekv); - path.setFillRule(Qt::WindingFill); - } - return path; -} - -//--------------------------------------------------------------------------------------------------------------------- -QPointF VEquidistant::StartSegment(const VDetail &detail, const int &i) const -{ - QPointF begin; - if (detail.CountNode() > 1) - { - if (i == 0) - { - if (detail.at(detail.CountNode()-1).getTypeTool() == Tool::NodePoint) - { - begin = data->GeometricObject(detail.at(detail.CountNode()-1).getId())->toQPointF(); - } - } - else - { - if (detail.at(i-1).getTypeTool() == Tool::NodePoint) - { - begin = data->GeometricObject(detail.at(i-1).getId())->toQPointF(); - } - } - } - return begin; -} - -//--------------------------------------------------------------------------------------------------------------------- -QPointF VEquidistant::EndSegment(const VDetail &detail, const int &i) const -{ - QPointF end; - if (detail.CountNode() > 2) - { - if (i == detail.CountNode() - 1) - { - if (detail.at(0).getTypeTool() == Tool::NodePoint) - { - end = data->GeometricObject(detail.at(0).getId())->toQPointF(); - } - } - else - { - if (detail.at(i+1).getTypeTool() == Tool::NodePoint) - { - end = data->GeometricObject(detail.at(i+1).getId())->toQPointF(); - } - } - } - return end; -} - -//--------------------------------------------------------------------------------------------------------------------- -QVector VEquidistant::biasPoints(const QVector &points, const qreal &mx, const qreal &my) -{ - QVector p; - for (qint32 i = 0; i < points.size(); ++i) - { - QPointF point = points.at(i); - point.setX(point.x() + mx); - point.setY(point.y() + my); - p.append(point); - } - return p; -} - -//--------------------------------------------------------------------------------------------------------------------- -QVector VEquidistant::CorrectEquidistantPoints(const QVector &points) -{ - QVector correctPoints; - if (points.size()<4)//Better don't check if only three points. We can destroy equidistant. - { - qDebug()<<"Only three points."; - return points; - } - //Clear equivalent points - for (qint32 i = 0; i points, const EquidistantType &eqv, const qreal &width) -{ - QPainterPath ekv; - QVector ekvPoints; - if ( points.size() < 3 ) - { - qDebug()<<"Not enough points for building the equidistant."; - return ekv; - } - if (width <= 0) - { - qDebug()<<"Width <= 0."; - return ekv; - } - for (qint32 i = 0; i < points.size(); ++i ) - { - if (i != points.size()-1) - { - if (points.at(i) == points.at(i+1)) - { - points.remove(i+1); - } - } - else - { - if (points.at(i) == points.at(0)) - { - points.remove(i); - } - } - } - if (eqv == EquidistantType::CloseEquidistant) - { - points.append(points.at(0)); - } - for (qint32 i = 0; i < points.size(); ++i ) - { - if ( i == 0 && eqv == EquidistantType::CloseEquidistant) - {//first point, polyline closed - ekvPoints< VEquidistant::CheckLoops(const QVector &points) -{ - QVector ekvPoints; - /*If we got less than 4 points no need seek loops.*/ - if (points.size() < 4) - { - qDebug()<<"Less then 4 points. Doesn't need check for loops."; - return points; - } - bool closed = false; - if (points.at(0) == points.at(points.size()-1)) - { - closed = true; - } - qint32 i, j; - for (i = 0; i < points.size(); ++i) - { - /*Last three points no need check.*/ - if (i >= points.size()-3) - { - ekvPoints.append(points.at(i)); - continue; - } - QPointF crosPoint; - QLineF::IntersectType intersect = QLineF::NoIntersection; - QLineF line1(points.at(i), points.at(i+1)); - for (j = i+2; j < points.size()-1; ++j) - { - QLineF line2(points.at(j), points.at(j+1)); - intersect = line1.intersect(line2, &crosPoint); - if (intersect == QLineF::BoundedIntersection) - { - break; - } - } - if (intersect == QLineF::BoundedIntersection) - { - if (i == 0 && j+1 == points.size()-1 && closed) - { - /*We got closed contour.*/ - ekvPoints.append(points.at(i)); - } - else - { - /*We found loop.*/ - ekvPoints.append(points.at(i)); - ekvPoints.append(crosPoint); - i = j; - } - } - else - { - /*We did not found loop.*/ - ekvPoints.append(points.at(i)); - } - } - return ekvPoints; -} - -//--------------------------------------------------------------------------------------------------------------------- -QVector VEquidistant::EkvPoint(const QLineF &line1, const QLineF &line2, const qreal &width) -{ - SCASSERT(width > 0); - QVector points; - if (line1.p2() != line2.p2()) - { - qDebug()<<"Last points of two lines must be equal."; - return QVector(); - } - QPointF CrosPoint; - QLineF bigLine1 = ParallelLine(line1, width ); - QLineF bigLine2 = ParallelLine(QLineF(line2.p2(), line2.p1()), width ); - QLineF::IntersectType type = bigLine1.intersect( bigLine2, &CrosPoint ); - switch (type) - { - case (QLineF::BoundedIntersection): - points.append(CrosPoint); - return points; - break; - case (QLineF::UnboundedIntersection): - { - QLineF line( line1.p2(), CrosPoint ); - const qreal length = line.length(); - if (length > width*2.4) - { // Cutting too long an acute angle - line.setLength(width); // Not sure about width value here - QLineF cutLine(line.p2(), CrosPoint); // Cut line is a perpendicular - cutLine.setLength(length); // Decided take this length - - // We do not check intersection type because intersection must alwayse exist - QPointF px; - cutLine.setAngle(cutLine.angle()+90); - QLineF::IntersectType type = bigLine1.intersect( cutLine, &px ); - if (type == QLineF::NoIntersection) - { - qDebug()<<"Couldn't find intersection with cut line."; - } - points.append(px); - - cutLine.setAngle(cutLine.angle()-180); - type = bigLine2.intersect( cutLine, &px ); - if (type == QLineF::NoIntersection) - { - qDebug()<<"Couldn't find intersection with cut line."; - } - points.append(px); - } - else - { - points.append(CrosPoint); - return points; - } - break; - } - case (QLineF::NoIntersection): - /*If we have correct lines this means lines lie on a line.*/ - points.append(bigLine1.p2()); - return points; - break; - default: - break; - } - return points; -} - -//--------------------------------------------------------------------------------------------------------------------- -QLineF VEquidistant::ParallelLine(const QLineF &line, qreal width) -{ - SCASSERT(width > 0); - QLineF paralel = QLineF (SingleParallelPoint(line, 90, width), SingleParallelPoint(QLineF(line.p2(), line.p1()), - -90, width)); - return paralel; -} - -//--------------------------------------------------------------------------------------------------------------------- -QPointF VEquidistant::SingleParallelPoint(const QLineF &line, const qreal &angle, const qreal &width) -{ - SCASSERT(width > 0); - QLineF pLine = line; - pLine.setAngle( pLine.angle() + angle ); - pLine.setLength( width ); - return pLine.p2(); -} diff --git a/src/app/geometry/vequidistant.h b/src/app/geometry/vequidistant.h deleted file mode 100644 index 9e19df5d5..000000000 --- a/src/app/geometry/vequidistant.h +++ /dev/null @@ -1,113 +0,0 @@ -/************************************************************************ - ** - ** @file vequidistant.h - ** @author Roman Telezhynskyi - ** @date 28 1, 2014 - ** - ** @brief - ** @copyright - ** This source code is part of the Valentine project, a pattern making - ** program, whose allow create and modeling patterns of clothing. - ** Copyright (C) 2013 Valentina project - ** 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 . - ** - *************************************************************************/ - -#ifndef VEQUIDISTANT_H -#define VEQUIDISTANT_H - -#include "vdetail.h" - -class QPainterPath; -class VContainer; -class QPointF; -class QLineF; - -/** - * @brief The VEquidistant class calculate equidistant for detail. - */ -class VEquidistant -{ -public: - VEquidistant(const VContainer *data); - ~VEquidistant(){} - /** - * @brief ContourPath create painter path for detail. - * @param idDetail id of detail. - * @param data container with objects (points, arcs, splines). - * @return return painter path of contour detail. - */ - QPainterPath ContourPath(const quint32 &idDetail) const; -private: - Q_DISABLE_COPY(VEquidistant) - const VContainer *data; - /** - * @brief biasPoints bias point. - * @param points vector of points. - * @param mx offset respect to x. - * @param my offset respect to y. - * @return new vector biased points. - */ - static QVector biasPoints(const QVector &points, const qreal &mx, const qreal &my); - /** - * @brief CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant. - * @param points list of points equdistant. - * @return corrected list. - */ - static QVector CorrectEquidistantPoints(const QVector &points); - /** - * @brief Equidistant create equidistant painter path for detail. - * @param points vector of points. - * @param eqv type of equidistant. - * @param width width of equidistant. - * @return return painter path of equidistant. - */ - static QPainterPath Equidistant(QVector points, const EquidistantType &eqv, const qreal &width); - /** - * @brief CheckLoops seek and delete loops in equidistant. - * @param points vector of points of equidistant. - * @return vector of points of equidistant. - */ - static QVector CheckLoops(const QVector &points); - /** - * @brief EkvPoint return vector of points of equidistant two lines. Last point of two lines must be equal. - * @param line1 first line. - * @param line2 second line. - * @param width width of equidistant. - * @return vector of points. - */ - static QVector EkvPoint(const QLineF &line1, const QLineF &line2, const qreal &width); - /** - * @brief ParallelLine create parallel line. - * @param line starting line. - * @param width width to parallel line. - * @return parallel line. - */ - static QLineF ParallelLine(const QLineF &line, qreal width ); - /** - * @brief SingleParallelPoint return point of parallel line. - * @param line starting line. - * @param angle angle in degree. - * @param width width to parallel line. - * @return point of parallel line. - */ - static QPointF SingleParallelPoint(const QLineF &line, const qreal &angle, const qreal &width); - - QPointF StartSegment(const VDetail &detail, const int &i) const; - QPointF EndSegment(const VDetail &detail, const int &i) const; -}; - -#endif // VEQUIDISTANT_H diff --git a/src/app/mainwindow.cpp b/src/app/mainwindow.cpp index be206e7cb..4396651ed 100644 --- a/src/app/mainwindow.cpp +++ b/src/app/mainwindow.cpp @@ -29,7 +29,6 @@ #include "mainwindow.h" #include "ui_mainwindow.h" #include "geometry/vspline.h" -#include "geometry/vequidistant.h" #include "exception/vexceptionobjecterror.h" #include "exception/vexceptionconversionerror.h" #include "exception/vexceptionemptyparameter.h" @@ -1908,7 +1907,7 @@ void MainWindow::ActionLayout(bool checked) { Q_UNUSED(checked); ActionDetails(true);//Get all list of details. - QVector listDetails; + QVector listDetails; const QHash *details = pattern->DataDetails(); if (details->count() == 0) { @@ -1919,8 +1918,14 @@ void MainWindow::ActionLayout(bool checked) while (idetail.hasNext()) { idetail.next(); - QPainterPath path = VEquidistant(pattern).ContourPath(idetail.key()); - listDetails.append(new VItem(path, listDetails.size())); + VLayoutDetail det = VLayoutDetail(); + det.SetCountour(idetail.value().ContourPoints(pattern)); + det.SetSeamAllowencePoints(idetail.value().SeamAllowancePoints(pattern)); + det.setSeamAllowance(idetail.value().getSeamAllowance()); + det.setName(idetail.value().getName()); + det.SetLayoutAllowence(); + + listDetails.append(det); } QString description = doc->GetDescription(); diff --git a/src/app/mainwindow.h b/src/app/mainwindow.h index 0463bd06c..20f1dc927 100644 --- a/src/app/mainwindow.h +++ b/src/app/mainwindow.h @@ -32,12 +32,12 @@ #include #include "widgets/vmaingraphicsscene.h" #include "widgets/vmaingraphicsview.h" -#include "widgets/vitem.h" #include "dialogs/dialogs.h" #include "tools/vtooldetail.h" #include "tools/vtooluniondetails.h" #include "tools/drawTools/drawtools.h" #include "xml/vdomdocument.h" +#include "../libs/vlayout/vlayoutdetail.h" namespace Ui { @@ -136,7 +136,8 @@ signals: * @param listDetails list of details. * @param description pattern description. */ - void ModelChosen(QVector listDetails, const QString &curFile, const QString &description); + void ModelChosen(QVector listDetails, const QString &curFile, + const QString &description); void RefreshHistory(); protected: virtual void keyPressEvent(QKeyEvent *event); diff --git a/src/app/options.h b/src/app/options.h index 6c640a075..2a4e72fa0 100644 --- a/src/app/options.h +++ b/src/app/options.h @@ -118,7 +118,6 @@ enum class Source : char { FromGui, FromFile, FromTool }; enum class Draw : char { Calculation, Modeling }; enum class NodeDetail : char { Contour, Modeling }; enum class Contour : char { OpenContour, CloseContour }; -enum class EquidistantType : char { OpenEquidistant, CloseEquidistant }; enum class GOType : char { Point, Arc, Spline, SplinePath, Unknown }; enum class SplinePointPosition : char { FirstPoint, LastPoint }; enum class VarType : char { Measurement, Increment, LineLength, SplineLength, ArcLength, LineAngle, Unknown }; diff --git a/src/app/tablewindow.cpp b/src/app/tablewindow.cpp index 525c5fe2c..632b37f20 100644 --- a/src/app/tablewindow.cpp +++ b/src/app/tablewindow.cpp @@ -48,7 +48,7 @@ */ TableWindow::TableWindow(QWidget *parent) :QMainWindow(parent), numberDetal(nullptr), colission(nullptr), ui(new Ui::TableWindow), - listDetails(QVector()), outItems(false), collidingItems(false), tableScene(nullptr), + listDetails(QVector()), outItems(false), collidingItems(false), tableScene(nullptr), paper(nullptr), shadowPaper(nullptr), listOutItems(nullptr), listCollidingItems(QList()), indexDetail(0), sceneRect(QRectF()), fileName(QString()), description(QString()) { @@ -112,30 +112,30 @@ void TableWindow::AddPaper() */ void TableWindow::AddDetail() { - if (indexDetailclearSelection(); - VItem* Detail = listDetails[indexDetail]; - SCASSERT(Detail != nullptr); - connect(Detail, &VItem::itemOut, this, &TableWindow::itemOut); - connect(Detail, &VItem::itemColliding, this, &TableWindow::itemColliding); - connect(this, &TableWindow::LengthChanged, Detail, &VItem::LengthChanged); - Detail->setPen(QPen(Qt::black, 1)); - Detail->setBrush(QBrush(Qt::white)); - Detail->setPos(paper->boundingRect().center()); - Detail->setFlag(QGraphicsItem::ItemIsMovable, true); - Detail->setFlag(QGraphicsItem::ItemIsSelectable, true); - Detail->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); - Detail->setPaper(paper); - tableScene->addItem(Detail); - Detail->setSelected(true); - indexDetail++; - if (indexDetail==listDetails.count()) - { - ui->actionSave->setEnabled(true); - } - } - numberDetal->setText(QString(tr("%1 details left.")).arg(listDetails.count()-indexDetail)); +// if (indexDetailclearSelection(); +// VItem* Detail = listDetails[indexDetail]; +// SCASSERT(Detail != nullptr); +// connect(Detail, &VItem::itemOut, this, &TableWindow::itemOut); +// connect(Detail, &VItem::itemColliding, this, &TableWindow::itemColliding); +// connect(this, &TableWindow::LengthChanged, Detail, &VItem::LengthChanged); +// Detail->setPen(QPen(Qt::black, 1)); +// Detail->setBrush(QBrush(Qt::white)); +// Detail->setPos(paper->boundingRect().center()); +// Detail->setFlag(QGraphicsItem::ItemIsMovable, true); +// Detail->setFlag(QGraphicsItem::ItemIsSelectable, true); +// Detail->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); +// Detail->setPaper(paper); +// tableScene->addItem(Detail); +// Detail->setSelected(true); +// indexDetail++; +// if (indexDetail==listDetails.count()) +// { +// ui->actionSave->setEnabled(true); +// } +// } +// numberDetal->setText(QString(tr("%1 details left.")).arg(listDetails.count()-indexDetail)); } //--------------------------------------------------------------------------------------------------------------------- @@ -147,7 +147,7 @@ void TableWindow::AddDetail() /* * Get details for creation layout. */ -void TableWindow::ModelChosen(QVector listDetails, const QString &fileName, const QString &description) +void TableWindow::ModelChosen(QVector listDetails, const QString &fileName, const QString &description) { this->description = description; @@ -390,67 +390,67 @@ void TableWindow::itemOut(int number, bool flag) void TableWindow::itemColliding(QList list, int number) { //qDebug()<<"number="<1) - { - for ( int i = 0; i < listCollidingItems.count(); ++i ) - { - QList lis = listCollidingItems.at(i)->collidingItems(); - if (lis.size()-2 <= 0) - { - VItem * bitem = qgraphicsitem_cast ( listCollidingItems.at(i) ); - SCASSERT(bitem != nullptr); - bitem->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthMainLine()))); - listCollidingItems.removeAt(i); - } - } - } - else if (listCollidingItems.size()==1) - { - VItem * bitem = qgraphicsitem_cast ( listCollidingItems.at(0) ); - SCASSERT(bitem != nullptr); - bitem->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthMainLine()))); - listCollidingItems.clear(); - collidingItems = true; - } - } - else - { - collidingItems = true; - } - } - else - { - collidingItems = true; - } - } - else if (number==1) - { - if (list.contains(paper)==true) - { - list.removeAt(list.indexOf(paper)); - } - if (list.contains(shadowPaper)==true) - { - list.removeAt(list.indexOf(shadowPaper)); - } - for ( int i = 0; i < list.count(); ++i ) - { - if (listCollidingItems.contains(list.at(i))==false) - { - listCollidingItems.append(list.at(i)); - } - } - collidingItems = false; - } - qDebug()<<"itemColliding::outItems="<1) +// { +// for ( int i = 0; i < listCollidingItems.count(); ++i ) +// { +// QList lis = listCollidingItems.at(i)->collidingItems(); +// if (lis.size()-2 <= 0) +// { +// VItem * bitem = qgraphicsitem_cast ( listCollidingItems.at(i) ); +// SCASSERT(bitem != nullptr); +// bitem->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthMainLine()))); +// listCollidingItems.removeAt(i); +// } +// } +// } +// else if (listCollidingItems.size()==1) +// { +// VItem * bitem = qgraphicsitem_cast ( listCollidingItems.at(0) ); +// SCASSERT(bitem != nullptr); +// bitem->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthMainLine()))); +// listCollidingItems.clear(); +// collidingItems = true; +// } +// } +// else +// { +// collidingItems = true; +// } +// } +// else +// { +// collidingItems = true; +// } +// } +// else if (number==1) +// { +// if (list.contains(paper)==true) +// { +// list.removeAt(list.indexOf(paper)); +// } +// if (list.contains(shadowPaper)==true) +// { +// list.removeAt(list.indexOf(shadowPaper)); +// } +// for ( int i = 0; i < list.count(); ++i ) +// { +// if (listCollidingItems.contains(list.at(i))==false) +// { +// listCollidingItems.append(list.at(i)); +// } +// } +// collidingItems = false; +// } +// qDebug()<<"itemColliding::outItems="< #include -#include "widgets/vitem.h" + +#include "../../libs/vlayout/vlayoutdetail.h" namespace Ui { @@ -55,7 +56,8 @@ public: ~TableWindow(); public slots: - void ModelChosen(QVector listDetails, const QString &fileName, const QString &description); + void ModelChosen(QVector listDetails, const QString &fileName, + const QString &description); void StopTable(); @@ -96,7 +98,7 @@ private: Ui::TableWindow* ui; /** @brief listDetails list of details. */ - QVector listDetails; + QVector listDetails; /** @brief outItems true if we have details out paper sheet. */ bool outItems; diff --git a/src/app/tools/vtooldetail.cpp b/src/app/tools/vtooldetail.cpp index 9205c334f..38af795f4 100644 --- a/src/app/tools/vtooldetail.cpp +++ b/src/app/tools/vtooldetail.cpp @@ -30,7 +30,6 @@ #include "nodeDetails/nodedetails.h" #include "../geometry/varc.h" #include "../geometry/vsplinepath.h" -#include "../geometry/vequidistant.h" #include "../widgets/vmaingraphicsscene.h" #include "../dialogs/tools/dialogtool.h" #include "../dialogs/tools/dialogdetail.h" @@ -511,10 +510,8 @@ void VToolDetail::ShowVisualization(bool show) void VToolDetail::RefreshGeometry() { this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false); - QPainterPath path = VEquidistant(this->getData()).ContourPath(id); - this->setPath(path); - VDetail detail = VAbstractTool::data.GetDetail(id); + this->setPath(detail.ContourPath(this->getData())); this->setPos(detail.getMx(), detail.getMy()); this->setFlag(QGraphicsItem::ItemSendsGeometryChanges, true); } diff --git a/src/libs/vlayout/vabstractdetail.cpp b/src/libs/vlayout/vabstractdetail.cpp index 078a8b157..6df4a9176 100644 --- a/src/libs/vlayout/vabstractdetail.cpp +++ b/src/libs/vlayout/vabstractdetail.cpp @@ -29,6 +29,10 @@ #include "vabstractdetail.h" #include "vabstractdetail_p.h" +#include +#include +#include + //--------------------------------------------------------------------------------------------------------------------- /** * @brief VAbstractDetail default contructor. Create empty detail. @@ -166,3 +170,294 @@ void VAbstractDetail::setWidth(const qreal &value) { d->width = value; } + +//--------------------------------------------------------------------------------------------------------------------- +QVector VAbstractDetail::Equidistant(const QVector &points, const EquidistantType &eqv, qreal width) +{ + QVector ekvPoints; + + if (width <= 0) + { + qDebug()<<"Width <= 0."; + return QVector(); + } + + QVector p = CorrectEquidistantPoints(points); + if ( p.size() < 3 ) + { + qDebug()<<"Not enough points for building the equidistant."; + return QVector(); + } + + if (eqv == EquidistantType::CloseEquidistant) + { + p.append(points.at(0)); + } + for (qint32 i = 0; i < points.size(); ++i ) + { + if ( i == 0 && eqv == EquidistantType::CloseEquidistant) + {//first point, polyline closed + ekvPoints< VAbstractDetail::RemoveDublicates(const QVector &points) +{ + QVector p = points; + for(int i = 0; i < p.size(); i++) + { + QPointF current = p.at(i); + + for(int j = i; j < p.size(); j++) + { + if(j == i) + { + continue; + } + else + { + QPointF temp = p.at(j); + if(current == temp) + { + QVector::iterator iter = p.begin() + j; + p.erase(iter); + j--; + } + } + } + } + + return p; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief CorrectEquidistantPoints clear equivalent points and remove point on line from equdistant. + * @param points list of points equdistant. + * @return corrected list. + */ +QVector VAbstractDetail::CorrectEquidistantPoints(const QVector &points) +{ + QVector correctPoints; + if (points.size()<4)//Better don't check if only three points. We can destroy equidistant. + { + qDebug()<<"Only three points."; + return points; + } + + //Clear equivalent points + correctPoints = RemoveDublicates(points); + + if (correctPoints.size()<3) + { + return correctPoints; + } + //Remove point on line + QPointF point; + for (qint32 i = 1; i VAbstractDetail::CheckLoops(const QVector &points) +{ + QVector ekvPoints; + /*If we got less than 4 points no need seek loops.*/ + if (points.size() < 4) + { + qDebug()<<"Less then 4 points. Doesn't need check for loops."; + return points; + } + bool closed = false; + if (points.at(0) == points.at(points.size()-1)) + { + closed = true; + } + qint32 i, j; + for (i = 0; i < points.size(); ++i) + { + /*Last three points no need check.*/ + if (i >= points.size()-3) + { + ekvPoints.append(points.at(i)); + continue; + } + QPointF crosPoint; + QLineF::IntersectType intersect = QLineF::NoIntersection; + QLineF line1(points.at(i), points.at(i+1)); + for (j = i+2; j < points.size()-1; ++j) + { + QLineF line2(points.at(j), points.at(j+1)); + intersect = line1.intersect(line2, &crosPoint); + if (intersect == QLineF::BoundedIntersection) + { + break; + } + } + if (intersect == QLineF::BoundedIntersection) + { + if (i == 0 && j+1 == points.size()-1 && closed) + { + /*We got closed contour.*/ + ekvPoints.append(points.at(i)); + } + else + { + /*We found loop.*/ + ekvPoints.append(points.at(i)); + ekvPoints.append(crosPoint); + i = j; + } + } + else + { + /*We did not found loop.*/ + ekvPoints.append(points.at(i)); + } + } + return ekvPoints; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief EkvPoint return vector of points of equidistant two lines. Last point of two lines must be equal. + * @param line1 first line. + * @param line2 second line. + * @param width width of equidistant. + * @return vector of points. + */ +QVector VAbstractDetail::EkvPoint(const QLineF &line1, const QLineF &line2, const qreal &width) +{ + if (width <= 0) + { + return QVector(); + } + QVector points; + if (line1.p2() != line2.p2()) + { + qDebug()<<"Last points of two lines must be equal."; + return QVector(); + } + QPointF CrosPoint; + QLineF bigLine1 = ParallelLine(line1, width ); + QLineF bigLine2 = ParallelLine(QLineF(line2.p2(), line2.p1()), width ); + QLineF::IntersectType type = bigLine1.intersect( bigLine2, &CrosPoint ); + switch (type) + { + case (QLineF::BoundedIntersection): + points.append(CrosPoint); + return points; + break; + case (QLineF::UnboundedIntersection): + { + QLineF line( line1.p2(), CrosPoint ); + const qreal length = line.length(); + if (length > width*2.4) + { // Cutting too long an acute angle + line.setLength(width); // Not sure about width value here + QLineF cutLine(line.p2(), CrosPoint); // Cut line is a perpendicular + cutLine.setLength(length); // Decided take this length + + // We do not check intersection type because intersection must alwayse exist + QPointF px; + cutLine.setAngle(cutLine.angle()+90); + QLineF::IntersectType type = bigLine1.intersect( cutLine, &px ); + if (type == QLineF::NoIntersection) + { + qDebug()<<"Couldn't find intersection with cut line."; + } + points.append(px); + + cutLine.setAngle(cutLine.angle()-180); + type = bigLine2.intersect( cutLine, &px ); + if (type == QLineF::NoIntersection) + { + qDebug()<<"Couldn't find intersection with cut line."; + } + points.append(px); + } + else + { + points.append(CrosPoint); + return points; + } + break; + } + case (QLineF::NoIntersection): + /*If we have correct lines this means lines lie on a line.*/ + points.append(bigLine1.p2()); + return points; + break; + default: + break; + } + return points; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief ParallelLine create parallel line. + * @param line starting line. + * @param width width to parallel line. + * @return parallel line. + */ +QLineF VAbstractDetail::ParallelLine(const QLineF &line, qreal width) +{ + QLineF paralel = QLineF (SingleParallelPoint(line, 90, width), SingleParallelPoint(QLineF(line.p2(), line.p1()), + -90, width)); + return paralel; +} + +//--------------------------------------------------------------------------------------------------------------------- +/** + * @brief SingleParallelPoint return point of parallel line. + * @param line starting line. + * @param angle angle in degree. + * @param width width to parallel line. + * @return point of parallel line. + */ +QPointF VAbstractDetail::SingleParallelPoint(const QLineF &line, const qreal &angle, const qreal &width) +{ + QLineF pLine = line; + pLine.setAngle( pLine.angle() + angle ); + pLine.setLength( width ); + return pLine.p2(); +} diff --git a/src/libs/vlayout/vabstractdetail.h b/src/libs/vlayout/vabstractdetail.h index d22f0f4e7..f5c08f256 100644 --- a/src/libs/vlayout/vabstractdetail.h +++ b/src/libs/vlayout/vabstractdetail.h @@ -31,8 +31,12 @@ #include +#include "vlayoutdef.h" + class QString; class VAbstractDetailData; +class QPointF; +class QLineF; /** * @brief The VAbstractDetail class abstract class for all details. @@ -59,8 +63,17 @@ public: qreal getWidth() const; void setWidth(const qreal &value); + + static QVector Equidistant(const QVector &points, const EquidistantType &eqv, qreal width); private: QSharedDataPointer d; + + static QVector RemoveDublicates(const QVector &points); + static QVector CorrectEquidistantPoints(const QVector &points); + static QVector CheckLoops(const QVector &points); + static QVector EkvPoint(const QLineF &line1, const QLineF &line2, const qreal &width); + static QLineF ParallelLine(const QLineF &line, qreal width ); + static QPointF SingleParallelPoint(const QLineF &line, const qreal &angle, const qreal &width); }; #endif // VABSTRACTDETAIL_H diff --git a/src/libs/vlayout/vlayout.pri b/src/libs/vlayout/vlayout.pri index 2e203b6e1..c7ab13fdd 100644 --- a/src/libs/vlayout/vlayout.pri +++ b/src/libs/vlayout/vlayout.pri @@ -6,7 +6,9 @@ HEADERS += \ $$PWD/vlayoutgenerator.h \ $$PWD/vlayoutdetail.h \ $$PWD/vabstractdetail.h \ - $$PWD/vabstractdetail_p.h + $$PWD/vabstractdetail_p.h \ + $$PWD/vlayoutdetail_p.h \ + $$PWD/vlayoutdef.h SOURCES += \ $$PWD/stable.cpp \ diff --git a/src/libs/vlayout/vlayout.pro b/src/libs/vlayout/vlayout.pro index 96f9fd549..7cee445cc 100644 --- a/src/libs/vlayout/vlayout.pro +++ b/src/libs/vlayout/vlayout.pro @@ -7,9 +7,6 @@ # File with common stuff for whole project include(../../../Valentina.pri) -# We don't need gui library. -QT -= gui - # Name of library TARGET = vlayout diff --git a/src/libs/vlayout/vlayoutdef.h b/src/libs/vlayout/vlayoutdef.h new file mode 100644 index 000000000..25d09a59d --- /dev/null +++ b/src/libs/vlayout/vlayoutdef.h @@ -0,0 +1,34 @@ +/************************************************************************ + ** + ** @file vlayoutdef.h + ** @author Roman Telezhynskyi + ** @date 7 1, 2015 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2015 Valentina project + ** 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 . + ** + *************************************************************************/ + +#ifndef VLAYOUTDEF_H +#define VLAYOUTDEF_H + +enum class EquidistantType : char { OpenEquidistant, CloseEquidistant }; + +#endif // VLAYOUTDEF_H diff --git a/src/libs/vlayout/vlayoutdetail.cpp b/src/libs/vlayout/vlayoutdetail.cpp index 08d9f0f40..1e0c2dcd4 100644 --- a/src/libs/vlayout/vlayoutdetail.cpp +++ b/src/libs/vlayout/vlayoutdetail.cpp @@ -27,7 +27,146 @@ *************************************************************************/ #include "vlayoutdetail.h" +#include "vlayoutdetail_p.h" +//--------------------------------------------------------------------------------------------------------------------- VLayoutDetail::VLayoutDetail() + :VAbstractDetail(), d(new VLayoutDetailData) +{} + +//--------------------------------------------------------------------------------------------------------------------- +VLayoutDetail::VLayoutDetail(const VLayoutDetail &detail) + :VAbstractDetail(detail), d (detail.d) +{} + +//--------------------------------------------------------------------------------------------------------------------- +VLayoutDetail &VLayoutDetail::operator=(const VLayoutDetail &detail) { + if ( &detail == this ) + { + return *this; + } + VAbstractDetail::operator=(detail); + d = detail.d; + return *this; +} + +//--------------------------------------------------------------------------------------------------------------------- +VLayoutDetail::~VLayoutDetail() +{} + +//--------------------------------------------------------------------------------------------------------------------- +QVector VLayoutDetail::GetContour() const +{ + return d->contour; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutDetail::SetCountour(const QVector &points) +{ + d->contour = points; +} + +//--------------------------------------------------------------------------------------------------------------------- +QVector VLayoutDetail::GetSeamAllowencePoints() const +{ + return d->seamAllowence; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutDetail::SetSeamAllowencePoints(const QVector &points) +{ + d->seamAllowence = points; +} + +//--------------------------------------------------------------------------------------------------------------------- +QVector VLayoutDetail::GetLayoutAllowence() const +{ + return Map(d->layoutAllowence); +} + +//--------------------------------------------------------------------------------------------------------------------- +QMatrix VLayoutDetail::GetMatrix() const +{ + return d->matrix; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutDetail::SetMatrix(const QMatrix &matrix) +{ + d->matrix = matrix; +} + +//--------------------------------------------------------------------------------------------------------------------- +qreal VLayoutDetail::GetLayoutWidth() const +{ + return d->layoutWidth; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutDetail::SetLayoutWidth(const qreal &value) +{ + d->layoutWidth = value; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutDetail::translate(qreal dx, qreal dy) +{ + const QMatrix m = d->matrix.translate(dx, dy); + d->matrix = m; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutDetail::rotate(qreal degrees) +{ + const QMatrix m = d->matrix.rotate(degrees); + d->matrix = m; +} + +//--------------------------------------------------------------------------------------------------------------------- +int VLayoutDetail::EdgesCount() const +{ + return d->layoutAllowence.count()-1; +} + +//--------------------------------------------------------------------------------------------------------------------- +QLineF VLayoutDetail::Edge(int i) const +{ + if (i < 1 || i > EdgesCount()) + { // Doesn't exist such edge + return QLineF(); + } + const QLineF line(d->layoutAllowence.at(i-1), d->layoutAllowence.at(i)); + return line; +} + +//--------------------------------------------------------------------------------------------------------------------- +void VLayoutDetail::SetLayoutAllowence() +{ + if (d->layoutWidth > 0) + { + if (getSeamAllowance()) + { + d->layoutAllowence = Equidistant(d->seamAllowence, EquidistantType::CloseEquidistant, d->layoutWidth); + } + else + { + d->layoutAllowence = Equidistant(d->contour, EquidistantType::CloseEquidistant, d->layoutWidth); + } + } + else + { + d->layoutAllowence.clear(); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +QVector VLayoutDetail::Map(const QVector &points) const +{ + QVector p; + for (int i = 0; i < points.size(); ++i) + { + p.append(d->matrix.map(points.at(i))); + } + return p; } diff --git a/src/libs/vlayout/vlayoutdetail.h b/src/libs/vlayout/vlayoutdetail.h index 7aded6536..8699ef242 100644 --- a/src/libs/vlayout/vlayoutdetail.h +++ b/src/libs/vlayout/vlayoutdetail.h @@ -29,10 +29,46 @@ #ifndef VLAYOUTDETAIL_H #define VLAYOUTDETAIL_H -class VLayoutDetail +#include "vabstractdetail.h" + +#include +#include + +class VLayoutDetailData; + +class VLayoutDetail :public VAbstractDetail { public: VLayoutDetail(); + VLayoutDetail(const VLayoutDetail &detail); + VLayoutDetail &operator=(const VLayoutDetail &detail); + virtual ~VLayoutDetail(); + + QVector GetContour() const; + void SetCountour(const QVector &points); + + QVector GetSeamAllowencePoints() const; + void SetSeamAllowencePoints(const QVector &points); + + QVector GetLayoutAllowence() const; + void SetLayoutAllowence(); + + QMatrix GetMatrix() const; + void SetMatrix(const QMatrix &matrix); + + qreal GetLayoutWidth() const; + void SetLayoutWidth(const qreal &value); + + void translate(qreal dx, qreal dy); + void rotate(qreal degrees); + + int EdgesCount() const; + QLineF Edge(int i) const; + +private: + QSharedDataPointer d; + + QVector Map(const QVector &points) const; }; #endif // VLAYOUTDETAIL_H diff --git a/src/libs/vlayout/vlayoutdetail_p.h b/src/libs/vlayout/vlayoutdetail_p.h new file mode 100644 index 000000000..a15dd1e5e --- /dev/null +++ b/src/libs/vlayout/vlayoutdetail_p.h @@ -0,0 +1,77 @@ +/************************************************************************ + ** + ** @file vlayoutdetail_p.h + ** @author Roman Telezhynskyi + ** @date 3 1, 2015 + ** + ** @brief + ** @copyright + ** This source code is part of the Valentine project, a pattern making + ** program, whose allow create and modeling patterns of clothing. + ** Copyright (C) 2015 Valentina project + ** 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 . + ** + *************************************************************************/ + +#ifndef VLAYOUTDETAIL_P_H +#define VLAYOUTDETAIL_P_H + +#include +#include +#include +#include + +#ifdef Q_CC_GNU + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Weffc++" +#endif + +class VLayoutDetailData : public QSharedData +{ +public: + VLayoutDetailData() + :contour(QVector()), seamAllowence(QVector()), layoutAllowence(QVector()), + matrix(QMatrix()), layoutWidth(0) + {} + + VLayoutDetailData(const VLayoutDetailData &detail) + :QSharedData(detail), contour(detail.contour), seamAllowence(detail.seamAllowence), + layoutAllowence(detail.layoutAllowence), matrix(detail.matrix), layoutWidth(detail.layoutWidth) + {} + + ~VLayoutDetailData() {} + + /** @brief contour list of contour points. */ + QVector contour; + + /** @brief seamAllowence list of seam allowence points. */ + QVector seamAllowence; + + /** @brief layoutAllowence list of layout allowence points. */ + QVector layoutAllowence; + + /** @brief matrix transformation matrix*/ + QMatrix matrix; + + /** @brief layoutWidth value layout allowence width in pixels. */ + qreal layoutWidth; +}; + +#ifdef Q_CC_GNU + #pragma GCC diagnostic pop +#endif + +#endif // VLAYOUTDETAIL_P_H