Merge with feature. The tool Cubic Bezier curve.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2016-03-10 19:11:09 +02:00
commit 3c67fc2f65
47 changed files with 2372 additions and 556 deletions

View file

@ -135,6 +135,9 @@ void VToolOptionsPropertyBrowser::ShowItemOptions(QGraphicsItem *item)
case VToolSpline::Type:
ShowOptionsToolSpline(item);
break;
case VToolCubicBezier::Type:
ShowOptionsToolCubicBezier(item);
break;
case VToolSplinePath::Type:
ShowOptionsToolSplinePath(item);
break;
@ -243,6 +246,9 @@ void VToolOptionsPropertyBrowser::UpdateOptions()
case VToolSpline::Type:
UpdateOptionsToolSpline();
break;
case VToolCubicBezier::Type:
UpdateOptionsToolCubicBezier();
break;
case VToolSplinePath::Type:
UpdateOptionsToolSplinePath();
break;
@ -366,6 +372,9 @@ void VToolOptionsPropertyBrowser::userChangedData(VProperty *property)
case VToolSpline::Type:
ChangeDataToolSpline(prop);
break;
case VToolCubicBezier::Type:
ChangeDataToolCubicBezier(prop);
break;
case VToolSplinePath::Type:
ChangeDataToolSplinePath(prop);
break;
@ -1346,6 +1355,31 @@ void VToolOptionsPropertyBrowser::ChangeDataToolSpline(VProperty *property)
}
}
//---------------------------------------------------------------------------------------------------------------------
void VToolOptionsPropertyBrowser::ChangeDataToolCubicBezier(VProperty *property)
{
SCASSERT(property != nullptr)
const QVariant value = property->data(VProperty::DPC_Data, Qt::DisplayRole);
const QString id = propertyToId[property];
auto i = qgraphicsitem_cast<VToolCubicBezier *>(currentItem);
SCASSERT(i != nullptr);
switch (PropertiesList().indexOf(id))
{
case 0: // AttrName
Q_UNREACHABLE();//The attribute is read only
break;
case 27: // AttrTypeColor
i->SetLineColor(value.toString());
break;
default:
qWarning()<<"Unknown property type. id = "<<id;
break;
}
}
//---------------------------------------------------------------------------------------------------------------------
void VToolOptionsPropertyBrowser::ChangeDataToolSplinePath(VProperty *property)
{
@ -1762,6 +1796,17 @@ void VToolOptionsPropertyBrowser::ShowOptionsToolSpline(QGraphicsItem *item)
AddPropertyLineColor(i, tr("Color"), VAbstractTool::ColorsList(), AttrColor);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolOptionsPropertyBrowser::ShowOptionsToolCubicBezier(QGraphicsItem *item)
{
auto i = qgraphicsitem_cast<VToolCubicBezier *>(item);
i->ShowVisualization(true);
formView->setTitle(tr("Cubic bezier curve"));
AddPropertyObjectName(i, tr("Name"), true);
AddPropertyLineColor(i, tr("Color"), VAbstractTool::ColorsList(), AttrColor);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolOptionsPropertyBrowser::ShowOptionsToolSplinePath(QGraphicsItem *item)
{
@ -2190,6 +2235,15 @@ void VToolOptionsPropertyBrowser::UpdateOptionsToolSpline()
idToProperty[AttrColor]->setValue(VLineColorProperty::IndexOfColor(VAbstractTool::ColorsList(), i->GetLineColor()));
}
//---------------------------------------------------------------------------------------------------------------------
void VToolOptionsPropertyBrowser::UpdateOptionsToolCubicBezier()
{
auto i = qgraphicsitem_cast<VToolCubicBezier *>(currentItem);
idToProperty[AttrName]->setValue(i->name());
idToProperty[AttrColor]->setValue(VLineColorProperty::IndexOfColor(VAbstractTool::ColorsList(), i->GetLineColor()));
}
//---------------------------------------------------------------------------------------------------------------------
void VToolOptionsPropertyBrowser::UpdateOptionsToolSplinePath()
{

View file

@ -138,6 +138,7 @@ private:
void ChangeDataToolPointFromArcAndTangent(VPE::VProperty *property);
void ChangeDataToolShoulderPoint(VPE::VProperty *property);
void ChangeDataToolSpline(VPE::VProperty *property);
void ChangeDataToolCubicBezier(VPE::VProperty *property);
void ChangeDataToolSplinePath(VPE::VProperty *property);
void ChangeDataToolTriangle(VPE::VProperty *property);
void ChangeDataToolLineIntersectAxis(VPE::VProperty *property);
@ -166,6 +167,7 @@ private:
void ShowOptionsToolPointFromArcAndTangent(QGraphicsItem *item);
void ShowOptionsToolShoulderPoint(QGraphicsItem *item);
void ShowOptionsToolSpline(QGraphicsItem *item);
void ShowOptionsToolCubicBezier(QGraphicsItem *item);
void ShowOptionsToolSplinePath(QGraphicsItem *item);
void ShowOptionsToolTriangle(QGraphicsItem *item);
void ShowOptionsToolLineIntersectAxis(QGraphicsItem *item);
@ -194,6 +196,7 @@ private:
void UpdateOptionsToolPointFromArcAndTangent();
void UpdateOptionsToolShoulderPoint();
void UpdateOptionsToolSpline();
void UpdateOptionsToolCubicBezier();
void UpdateOptionsToolSplinePath();
void UpdateOptionsToolTriangle();
void UpdateOptionsToolLineIntersectAxis();

View file

@ -29,6 +29,7 @@
#include "dialoghistory.h"
#include "ui_dialoghistory.h"
#include "../vgeometry/varc.h"
#include "../vgeometry/vcubicbezier.h"
#include "../vgeometry/vsplinepath.h"
#include "../vgeometry/vpointf.h"
#include "../vtools/tools/vabstracttool.h"
@ -282,6 +283,13 @@ QString DialogHistory::Record(const VToolRecord &tool)
SCASSERT(spl != nullptr);
return QString(tr("Curve %1_%2")).arg(PointName(spl->GetP1().id())).arg(PointName(spl->GetP4().id()));
}
case Tool::CubicBezier:
{
const QSharedPointer<VCubicBezier> spl = data->GeometricObject<VCubicBezier>(tool.getId());
SCASSERT(spl != nullptr);
return QString(tr("Cubic bezier curve %1_%2")).arg(PointName(spl->GetP1().id()))
.arg(PointName(spl->GetP4().id()));
}
case Tool::Arc:
{
const QSharedPointer<VArc> arc = data->GeometricObject<VArc>(tool.getId());

View file

@ -783,6 +783,15 @@ void MainWindow::ToolSpline(bool checked)
&MainWindow::ApplyDialog<VToolSpline>);
}
//---------------------------------------------------------------------------------------------------------------------
void MainWindow::ToolCubicBezier(bool checked)
{
SetToolButtonWithApply<DialogCubicBezier>(checked, Tool::CubicBezier, ":/cursor/cubic_bezier_cursor.png",
tr("Select first curve point"),
&MainWindow::ClosedDialogWithApply<VToolCubicBezier>,
&MainWindow::ApplyDialog<VToolCubicBezier>);
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief ToolCutSpline handler tool CutSpline.
@ -1603,6 +1612,7 @@ void MainWindow::InitToolButtons()
connect(ui->toolButtonBisector, &QToolButton::clicked, this, &MainWindow::ToolBisector);
connect(ui->toolButtonLineIntersect, &QToolButton::clicked, this, &MainWindow::ToolLineIntersect);
connect(ui->toolButtonSpline, &QToolButton::clicked, this, &MainWindow::ToolSpline);
connect(ui->toolButtonCubicBezier, &QToolButton::clicked, this, &MainWindow::ToolCubicBezier);
connect(ui->toolButtonArc, &QToolButton::clicked, this, &MainWindow::ToolArc);
connect(ui->toolButtonSplinePath, &QToolButton::clicked, this, &MainWindow::ToolSplinePath);
connect(ui->toolButtonPointOfContact, &QToolButton::clicked, this, &MainWindow::ToolPointOfContact);
@ -1709,6 +1719,9 @@ void MainWindow::CancelTool()
case Tool::Spline:
ui->toolButtonSpline->setChecked(false);
break;
case Tool::CubicBezier:
ui->toolButtonCubicBezier->setChecked(false);
break;
case Tool::Arc:
ui->toolButtonArc->setChecked(false);
break;
@ -2933,6 +2946,7 @@ void MainWindow::SetEnableTool(bool enable)
ui->toolButtonBisector->setEnabled(drawTools);
ui->toolButtonLineIntersect->setEnabled(drawTools);
ui->toolButtonSpline->setEnabled(drawTools);
ui->toolButtonCubicBezier->setEnabled(drawTools);
ui->toolButtonArc->setEnabled(drawTools);
ui->toolButtonSplinePath->setEnabled(drawTools);
ui->toolButtonPointOfContact->setEnabled(drawTools);

View file

@ -108,6 +108,7 @@ public slots:
void ToolBisector(bool checked);
void ToolLineIntersect(bool checked);
void ToolSpline(bool checked);
void ToolCubicBezier(bool checked);
void ToolCutSpline(bool checked);
void ToolArc(bool checked);
void ToolSplinePath(bool checked);

View file

@ -462,7 +462,7 @@
<x>0</x>
<y>0</y>
<width>130</width>
<height>156</height>
<height>196</height>
</rect>
</property>
<property name="sizePolicy">
@ -540,7 +540,33 @@
</property>
</widget>
</item>
<item row="2" column="0">
<item row="1" column="0">
<widget class="QToolButton" name="toolButtonCubicBezier">
<property name="enabled">
<bool>false</bool>
</property>
<property name="toolTip">
<string>Curve tool which uses point as control handle</string>
</property>
<property name="text">
<string notr="true">...</string>
</property>
<property name="icon">
<iconset resource="share/resources/toolicon.qrc">
<normaloff>:/toolicon/32x32/cubic_bezier.png</normaloff>:/toolicon/32x32/cubic_bezier.png</iconset>
</property>
<property name="iconSize">
<size>
<width>32</width>
<height>32</height>
</size>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QToolButton" name="toolButtonSplinePath">
<property name="enabled">
<bool>false</bool>
@ -566,7 +592,7 @@
</property>
</widget>
</item>
<item row="2" column="1">
<item row="2" column="0">
<widget class="QToolButton" name="toolButtonSplinePathCutPoint">
<property name="enabled">
<bool>false</bool>
@ -592,7 +618,7 @@
</property>
</widget>
</item>
<item row="3" column="0">
<item row="2" column="1">
<widget class="QToolButton" name="toolButtonCurveIntersectAxis">
<property name="enabled">
<bool>false</bool>
@ -618,7 +644,7 @@
</property>
</widget>
</item>
<item row="3" column="1">
<item row="3" column="0">
<widget class="QToolButton" name="toolButtonIntersectionCurves">
<property name="enabled">
<bool>false</bool>
@ -2140,9 +2166,6 @@
<header>vmaingraphicsview.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>toolButtonSplinePath</tabstop>
</tabstops>
<resources>
<include location="share/resources/toolicon.qrc"/>
<include location="../../libs/vmisc/share/resources/icon.qrc"/>

View file

@ -60,5 +60,7 @@
<file>cursor/true_darts_cursor@2x.png</file>
<file>cursor/intersection_curves_cursor.png</file>
<file>cursor/intersection_curves_cursor@2x.png</file>
<file>cursor/cubic_bezier_cursor.png</file>
<file>cursor/cubic_bezier_cursor@2x.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

View file

@ -58,5 +58,7 @@
<file>toolicon/32x32/true_darts@2x.png</file>
<file>toolicon/32x32/intersection_curves.png</file>
<file>toolicon/32x32/intersection_curves@2x.png</file>
<file>toolicon/32x32/cubic_bezier.png</file>
<file>toolicon/32x32/cubic_bezier@2x.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 895 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View file

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
width="32"
height="32"
id="svg3837"
inkscape:version="0.91 r"
sodipodi:docname="cubic_bezier.svg"
inkscape:export-filename="spline.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1855"
inkscape:window-height="1056"
id="namedview12"
showgrid="false"
inkscape:zoom="14.75"
inkscape:cx="-5.7288133"
inkscape:cy="12.164845"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs3839" />
<metadata
id="metadata3842">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1">
<path
style="fill:none;fill-rule:evenodd;stroke:#f73208;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 2.6949152,23.79661 C 7.1696576,10.712822 28.507924,22.118228 29.237288,7.6610169"
id="path4205"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cc" />
<path
d="m 4.6965534,23.856149 a 1.8239208,1.9086996 0 0 1 -3.6478415,0 1.8239208,1.9086996 0 1 1 3.6478415,0 z"
id="path2985-2-9"
style="fill:#000000;fill-opacity:1;stroke:#370000;stroke-width:1.57200003;stroke-linejoin:round;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.93950177"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:#370000;stroke-width:1.57200003;stroke-linejoin:round;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.93950177"
id="path9923"
d="m 30.866045,7.856149 a 1.8239208,1.9086996 0 0 1 -3.647842,0 1.8239208,1.9086996 0 1 1 3.647842,0 z" />
<path
d="m 9.8917173,10.441052 a 1.8239208,1.9086996 0 0 1 -3.6478415,0 1.8239208,1.9086996 0 1 1 3.6478415,0 z"
id="path2985-2-9-3"
style="fill:#000000;fill-opacity:1;stroke:#370000;stroke-width:1.57200003;stroke-linejoin:round;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.93950177"
inkscape:connector-curvature="0" />
<path
inkscape:connector-curvature="0"
style="fill:#000000;fill-opacity:1;stroke:#370000;stroke-width:1.57200003;stroke-linejoin:round;stroke-miterlimit:4.9000001;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.93950177"
id="path9923-8"
d="m 24.806972,22.034039 a 1.823921,1.9086998 0 0 1 -3.647842,0 1.823921,1.9086998 0 1 1 3.647842,0 z" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View file

@ -43,6 +43,7 @@
#include "../qmuparser/qmuparsererror.h"
#include "../vgeometry/varc.h"
#include "../vgeometry/vsplinepath.h"
#include "../vgeometry/vcubicbezier.h"
#include "../core/vapplication.h"
#include "../vpatterndb/calculator.h"
@ -1938,6 +1939,46 @@ void VPattern::ParseToolSpline(VMainGraphicsScene *scene, QDomElement &domElemen
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPattern::ParseToolCubicBezier(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse)
{
SCASSERT(scene != nullptr);
Q_ASSERT_X(not domElement.isNull(), Q_FUNC_INFO, "domElement is null");
try
{
quint32 id = 0;
ToolsCommonAttributes(domElement, id);
const quint32 point1 = GetParametrUInt(domElement, AttrPoint1, NULL_ID_STR);
const quint32 point2 = GetParametrUInt(domElement, AttrPoint2, NULL_ID_STR);
const quint32 point3 = GetParametrUInt(domElement, AttrPoint3, NULL_ID_STR);
const quint32 point4 = GetParametrUInt(domElement, AttrPoint4, NULL_ID_STR);
const QString color = GetParametrString(domElement, AttrColor, ColorBlack);
const quint32 duplicate = GetParametrUInt(domElement, AttrDuplicate, "0");
auto p1 = data->GeometricObject<VPointF>(point1);
auto p2 = data->GeometricObject<VPointF>(point2);
auto p3 = data->GeometricObject<VPointF>(point3);
auto p4 = data->GeometricObject<VPointF>(point4);
VCubicBezier *spline = new VCubicBezier(*p1, *p2, *p3, *p4);
if (duplicate > 0)
{
spline->SetDuplicate(duplicate);
}
VToolCubicBezier::Create(id, spline, color, scene, this, data, parse, Source::FromFile);
}
catch (const VExceptionBadId &e)
{
VExceptionObjectError excep(tr("Error creating or updating cubic bezier curve"), domElement);
excep.AddMoreInformation(e.ErrorMessage());
throw excep;
}
}
//---------------------------------------------------------------------------------------------------------------------
void VPattern::ParseOldToolSplinePath(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse)
{
@ -2100,10 +2141,22 @@ void VPattern::ParseNodeSpline(const QDomElement &domElement, const Document &pa
quint32 idTool = 0;
SplinesCommonAttributes(domElement, id, idObject, idTool);
VSpline *spl = new VSpline(*data->GeometricObject<VSpline>(idObject));
spl->setIdObject(idObject);
spl->setMode(Draw::Modeling);
data->UpdateGObject(id, spl);
const auto obj = data->GetGObject(idObject);
if (obj->getType() == GOType::Spline)
{
VSpline *spl = new VSpline(*data->GeometricObject<VSpline>(idObject));
spl->setIdObject(idObject);
spl->setMode(Draw::Modeling);
data->UpdateGObject(id, spl);
}
else
{
VCubicBezier *spl = new VCubicBezier(*data->GeometricObject<VCubicBezier>(idObject));
spl->setIdObject(idObject);
spl->setMode(Draw::Modeling);
data->UpdateGObject(id, spl);
}
VNodeSpline::Create(this, data, id, idObject, parse, Source::FromFile, idTool);
}
catch (const VExceptionBadId &e)
@ -2377,7 +2430,8 @@ void VPattern::ParseSplineElement(VMainGraphicsScene *scene, QDomElement &domEle
<< VToolSplinePath::OldToolType /*2*/
<< VToolSplinePath::ToolType /*3*/
<< VNodeSpline::ToolType /*4*/
<< VNodeSplinePath::ToolType; /*5*/
<< VNodeSplinePath::ToolType /*5*/
<< VToolCubicBezier::ToolType; /*6*/
switch (splines.indexOf(type))
{
case 0: //VToolSpline::OldToolType
@ -2404,6 +2458,10 @@ void VPattern::ParseSplineElement(VMainGraphicsScene *scene, QDomElement &domEle
qCDebug(vXML, "VNodeSplinePath.");
ParseNodeSplinePath(domElement, parse);
break;
case 6: //VToolCubicBezier::ToolType
qCDebug(vXML, "VToolCubicBezier.");
ParseToolCubicBezier(scene, domElement, parse);
break;
default:
VException e(tr("Unknown spline type '%1'.").arg(type));
throw e;

View file

@ -171,6 +171,7 @@ private:
void ParseOldToolSpline(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse);
void ParseToolSpline(VMainGraphicsScene *scene, QDomElement &domElement, const Document &parse);
void ParseToolCubicBezier(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse);
// TODO. Delete if minimal supported version is 0.2.7
void ParseOldToolSplinePath(VMainGraphicsScene *scene, const QDomElement &domElement, const Document &parse);

View file

@ -100,6 +100,7 @@ const QString AttrP2Line2 = QStringLiteral("p2Line2");
const QString AttrPShoulder = QStringLiteral("pShoulder");
const QString AttrPoint1 = QStringLiteral("point1");
const QString AttrPoint2 = QStringLiteral("point2");
const QString AttrPoint3 = QStringLiteral("point3");
const QString AttrPoint4 = QStringLiteral("point4");
const QString AttrKAsm1 = QStringLiteral("kAsm1");
const QString AttrKAsm2 = QStringLiteral("kAsm2");

View file

@ -102,6 +102,7 @@ extern const QString AttrP2Line2;
extern const QString AttrPShoulder;
extern const QString AttrPoint1;
extern const QString AttrPoint2;
extern const QString AttrPoint3;
extern const QString AttrPoint4;
extern const QString AttrKAsm1;// TODO. Delete if minimal supported version is 0.2.7
extern const QString AttrKAsm2;// TODO. Delete if minimal supported version is 0.2.7

View file

@ -198,6 +198,8 @@
<xs:attribute name="length1" type="xs:string"></xs:attribute>
<xs:attribute name="length2" type="xs:string"></xs:attribute>
<xs:attribute name="point1" type="xs:unsignedInt"></xs:attribute>
<xs:attribute name="point2" type="xs:unsignedInt"></xs:attribute>
<xs:attribute name="point3" type="xs:unsignedInt"></xs:attribute>
<xs:attribute name="point4" type="xs:unsignedInt"></xs:attribute>
<xs:attribute name="color" type="colors"></xs:attribute>
<xs:attribute name="duplicate" type="xs:unsignedInt"></xs:attribute>

View file

@ -0,0 +1,547 @@
/************************************************************************
**
** @file vabstractcubicbezier.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 8 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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 "vabstractcubicbezier.h"
#include "../vgeometry/vpointf.h"
#include <QPainterPath>
#include <QDebug>
//---------------------------------------------------------------------------------------------------------------------
VAbstractCubicBezier::VAbstractCubicBezier(const GOType &type, const quint32 &idObject, const Draw &mode)
: VAbstractCurve(type, idObject, mode)
{
}
//---------------------------------------------------------------------------------------------------------------------
VAbstractCubicBezier::VAbstractCubicBezier(const VAbstractCubicBezier &curve)
: VAbstractCurve(curve)
{
}
//---------------------------------------------------------------------------------------------------------------------
VAbstractCubicBezier &VAbstractCubicBezier::operator=(const VAbstractCubicBezier &curve)
{
if ( &curve == this )
{
return *this;
}
VAbstractCurve::operator=(curve);
return *this;
}
//---------------------------------------------------------------------------------------------------------------------
VAbstractCubicBezier::~VAbstractCubicBezier()
{
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief CutSpline cut spline.
* @param length length first spline
* @param spl1p2 second point of first spline
* @param spl1p3 third point of first spline
* @param spl2p2 second point of second spline
* @param spl2p3 third point of second spline
* @return point of cutting. This point is forth point of first spline and first point of second spline.
*/
QPointF VAbstractCubicBezier::CutSpline(qreal length, QPointF &spl1p2, QPointF &spl1p3, QPointF &spl2p2,
QPointF &spl2p3) const
{
//Always need return two splines, so we must correct wrong length.
if (length < GetLength()*0.02)
{
length = GetLength()*0.02;
}
else if ( length > GetLength()*0.98)
{
length = GetLength()*0.98;
}
// Very stupid way find correct value of t.
// Better first compare with t = 0.5. Find length of spline.
// If length larger, take t = 0.75 and so on.
// If length less, take t = 0.25 and so on.
qreal parT = 0;
qreal step = 0.001;
while (1)
{
parT = parT + step;
qreal splLength = LengthT(parT);
if (splLength >= length || parT > 1)
{
break;
}
}
QLineF seg1_2 ( GetP1 ().toQPointF(), GetControlPoint1 () );
seg1_2.setLength(seg1_2.length () * parT);
QPointF p12 = seg1_2.p2();
QLineF seg2_3 ( GetControlPoint1(), GetControlPoint2 () );
seg2_3.setLength(seg2_3.length () * parT);
QPointF p23 = seg2_3.p2();
QLineF seg12_23 ( p12, p23 );
seg12_23.setLength(seg12_23.length () * parT);
QPointF p123 = seg12_23.p2();
QLineF seg3_4 ( GetControlPoint2 (), GetP4 ().toQPointF() );
seg3_4.setLength(seg3_4.length () * parT);
QPointF p34 = seg3_4.p2();
QLineF seg23_34 ( p23, p34 );
seg23_34.setLength(seg23_34.length () * parT);
QPointF p234 = seg23_34.p2();
QLineF seg123_234 ( p123, p234 );
seg123_234.setLength(seg123_234.length () * parT);
QPointF p1234 = seg123_234.p2();
spl1p2 = p12;
spl1p3 = p123;
spl2p2 = p234;
spl2p3 = p34;
return p1234;
}
//---------------------------------------------------------------------------------------------------------------------
void VAbstractCubicBezier::CreateName()
{
QString name = SPL_ + QString("%1_%2").arg(GetP1().name()).arg(GetP4().name());
if (GetDuplicate() > 0)
{
name += QString("_%1").arg(GetDuplicate());
}
setName(name);
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief CalcSqDistance calculate squared distance.
* @param x1 х coordinate first point.
* @param y1 у coordinate first point.
* @param x2 х coordinate second point.
* @param y2 у coordinate second point.
* @return squared length.
*/
qreal VAbstractCubicBezier::CalcSqDistance(qreal x1, qreal y1, qreal x2, qreal y2)
{
const qreal dx = x2 - x1;
const qreal dy = y2 - y1;
return dx * dx + dy * dy;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief PointBezier_r find spline point using four point of spline.
* @param x1 х coordinate first point.
* @param y1 у coordinate first point.
* @param x2 х coordinate first control point.
* @param y2 у coordinate first control point.
* @param x3 х coordinate second control point.
* @param y3 у coordinate second control point.
* @param x4 х coordinate last point.
* @param y4 у coordinate last point.
* @param level level of recursion. In the begin 0.
* @param px list х coordinat spline points.
* @param py list у coordinat spline points.
*/
void VAbstractCubicBezier::PointBezier_r(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4,
qint16 level, QVector<qreal> &px, QVector<qreal> &py)
{
if (px.size() >= 2)
{
for (int i=1; i < px.size(); ++i)
{
if (QPointF(px.at(i-1), py.at(i-1)) == QPointF(px.at(i), py.at(i)))
{
qDebug("All neighbors points in path must be unique.");
}
}
}
const double curve_collinearity_epsilon = 1e-30;
const double curve_angle_tolerance_epsilon = 0.01;
const double m_angle_tolerance = 0.0;
enum curve_recursion_limit_e { curve_recursion_limit = 32 };
const double m_cusp_limit = 0.0;
double m_approximation_scale = 1.0;
double m_distance_tolerance_square;
m_distance_tolerance_square = 0.5 / m_approximation_scale;
m_distance_tolerance_square *= m_distance_tolerance_square;
if (level > curve_recursion_limit)
{
return;
}
// Calculate all the mid-points of the line segments
//----------------------
const double x12 = (x1 + x2) / 2;
const double y12 = (y1 + y2) / 2;
const double x23 = (x2 + x3) / 2;
const double y23 = (y2 + y3) / 2;
const double x34 = (x3 + x4) / 2;
const double y34 = (y3 + y4) / 2;
const double x123 = (x12 + x23) / 2;
const double y123 = (y12 + y23) / 2;
const double x234 = (x23 + x34) / 2;
const double y234 = (y23 + y34) / 2;
const double x1234 = (x123 + x234) / 2;
const double y1234 = (y123 + y234) / 2;
// Try to approximate the full cubic curve by a single straight line
//------------------
const double dx = x4-x1;
const double dy = y4-y1;
double d2 = fabs((x2 - x4) * dy - (y2 - y4) * dx);
double d3 = fabs((x3 - x4) * dy - (y3 - y4) * dx);
switch ((static_cast<int>(d2 > curve_collinearity_epsilon) << 1) +
static_cast<int>(d3 > curve_collinearity_epsilon))
{
case 0:
{
// All collinear OR p1==p4
//----------------------
double k = dx*dx + dy*dy;
if (k < 0.000000001)
{
d2 = CalcSqDistance(x1, y1, x2, y2);
d3 = CalcSqDistance(x4, y4, x3, y3);
}
else
{
k = 1 / k;
{
const double da1 = x2 - x1;
const double da2 = y2 - y1;
d2 = k * (da1*dx + da2*dy);
}
{
const double da1 = x3 - x1;
const double da2 = y3 - y1;
d3 = k * (da1*dx + da2*dy);
}
if (d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1)
{
// Simple collinear case, 1---2---3---4
// We can leave just two endpoints
return;
}
if (d2 <= 0)
{
d2 = CalcSqDistance(x2, y2, x1, y1);
}
else if (d2 >= 1)
{
d2 = CalcSqDistance(x2, y2, x4, y4);
}
else
{
d2 = CalcSqDistance(x2, y2, x1 + d2*dx, y1 + d2*dy);
}
if (d3 <= 0)
{
d3 = CalcSqDistance(x3, y3, x1, y1);
}
else if (d3 >= 1)
{
d3 = CalcSqDistance(x3, y3, x4, y4);
}
else
{
d3 = CalcSqDistance(x3, y3, x1 + d3*dx, y1 + d3*dy);
}
}
if (d2 > d3)
{
if (d2 < m_distance_tolerance_square)
{
px.append(x2);
py.append(y2);
return;
}
}
else
{
if (d3 < m_distance_tolerance_square)
{
px.append(x3);
py.append(y3);
return;
}
}
break;
}
case 1:
{
// p1,p2,p4 are collinear, p3 is significant
//----------------------
if (d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
if (m_angle_tolerance < curve_angle_tolerance_epsilon)
{
px.append(x23);
py.append(y23);
return;
}
// Angle Condition
//----------------------
double da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2));
if (da1 >= M_PI)
{
da1 = 2*M_PI - da1;
}
if (da1 < m_angle_tolerance)
{
px.append(x2);
py.append(y2);
px.append(x3);
py.append(y3);
return;
}
if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0)
{
if (da1 > m_cusp_limit)
{
px.append(x3);
py.append(y3);
return;
}
}
}
break;
}
case 2:
{
// p1,p3,p4 are collinear, p2 is significant
//----------------------
if (d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
if (m_angle_tolerance < curve_angle_tolerance_epsilon)
{
px.append(x23);
py.append(y23);
return;
}
// Angle Condition
//----------------------
double da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
if (da1 >= M_PI)
{
da1 = 2*M_PI - da1;
}
if (da1 < m_angle_tolerance)
{
px.append(x2);
py.append(y2);
px.append(x3);
py.append(y3);
return;
}
if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0)
{
if (da1 > m_cusp_limit)
{
px.append(x2);
py.append(y2);
return;
}
}
}
break;
}
case 3:
{
// Regular case
//-----------------
if ((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
// If the curvature doesn't exceed the distance_tolerance value
// we tend to finish subdivisions.
//----------------------
if (m_angle_tolerance < curve_angle_tolerance_epsilon)
{
px.append(x23);
py.append(y23);
return;
}
// Angle & Cusp Condition
//----------------------
const double k = atan2(y3 - y2, x3 - x2);
double da1 = fabs(k - atan2(y2 - y1, x2 - x1));
double da2 = fabs(atan2(y4 - y3, x4 - x3) - k);
if (da1 >= M_PI)
{
da1 = 2*M_PI - da1;
}
if (da2 >= M_PI)
{
da2 = 2*M_PI - da2;
}
if (da1 + da2 < m_angle_tolerance)
{
// Finally we can stop the recursion
//----------------------
px.append(x23);
py.append(y23);
return;
}
if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0)
{
if (da1 > m_cusp_limit)
{
px.append(x2);
py.append(y2);
return;
}
if (da2 > m_cusp_limit)
{
px.append(x3);
py.append(y3);
return;
}
}
}
break;
}
default:
break;
}
// Continue subdivision
//----------------------
PointBezier_r(x1, y1, x12, y12, x123, y123, x1234, y1234, static_cast<qint16>(level + 1), px, py);
PointBezier_r(x1234, y1234, x234, y234, x34, y34, x4, y4, static_cast<qint16>(level + 1), px, py);
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief GetCubicBezierPoints return list with cubic bezier curve points.
* @param p1 first spline point.
* @param p2 first control point.
* @param p3 second control point.
* @param p4 last spline point.
* @return list of points.
*/
QVector<QPointF> VAbstractCubicBezier::GetCubicBezierPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3,
const QPointF &p4)
{
QVector<QPointF> pvector;
QVector<qreal> x;
QVector<qreal> y;
QVector<qreal>& wx = x;
QVector<qreal>& wy = y;
x.append ( p1.x () );
y.append ( p1.y () );
PointBezier_r ( p1.x (), p1.y (), p2.x (), p2.y (),
p3.x (), p3.y (), p4.x (), p4.y (), 0, wx, wy );
x.append ( p4.x () );
y.append ( p4.y () );
for ( qint32 i = 0; i < x.count(); ++i )
{
pvector.append( QPointF ( x.at(i), y.at(i)) );
}
return pvector;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief LengthBezier return spline length using 4 spline point.
* @param p1 first spline point
* @param p2 first control point.
* @param p3 second control point.
* @param p4 last spline point.
* @return length.
*/
qreal VAbstractCubicBezier::LengthBezier(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
{
QPainterPath splinePath;
QVector<QPointF> points = GetCubicBezierPoints(p1, p2, p3, p4);
splinePath.moveTo(points.at(0));
for (qint32 i = 1; i < points.count(); ++i)
{
splinePath.lineTo(points.at(i));
}
return splinePath.length();
}
//---------------------------------------------------------------------------------------------------------------------
qreal VAbstractCubicBezier::LengthT(qreal t) const
{
if (t < 0 || t > 1)
{
qDebug()<<"Wrong value t.";
return 0;
}
QLineF seg1_2 ( GetP1 ().toQPointF(), GetControlPoint1 () );
seg1_2.setLength(seg1_2.length () * t);
const QPointF p12 = seg1_2.p2();
QLineF seg2_3 ( GetControlPoint1 (), GetControlPoint2 () );
seg2_3.setLength(seg2_3.length () * t);
const QPointF p23 = seg2_3.p2();
QLineF seg12_23 ( p12, p23 );
seg12_23.setLength(seg12_23.length () * t);
const QPointF p123 = seg12_23.p2();
QLineF seg3_4 ( GetControlPoint2 (), GetP4 ().toQPointF() );
seg3_4.setLength(seg3_4.length () * t);
const QPointF p34 = seg3_4.p2();
QLineF seg23_34 ( p23, p34 );
seg23_34.setLength(seg23_34.length () * t);
const QPointF p234 = seg23_34.p2();
QLineF seg123_234 ( p123, p234 );
seg123_234.setLength(seg123_234.length () * t);
const QPointF p1234 = seg123_234.p2();
return LengthBezier ( GetP1().toQPointF(), p12, p123, p1234);
}

View file

@ -0,0 +1,66 @@
/************************************************************************
**
** @file vabstractcubicbezier.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 8 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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/>.
**
*************************************************************************/
#ifndef VABSTRACTCUBICBEZIER_H
#define VABSTRACTCUBICBEZIER_H
#include "vabstractcurve.h"
class VPointF;
class VAbstractCubicBezier : public VAbstractCurve
{
public:
VAbstractCubicBezier(const GOType &type, const quint32 &idObject = NULL_ID, const Draw &mode = Draw::Calculation);
VAbstractCubicBezier(const VAbstractCubicBezier &curve);
VAbstractCubicBezier& operator= (const VAbstractCubicBezier &curve);
virtual ~VAbstractCubicBezier();
virtual VPointF GetP1 () const =0;
virtual VPointF GetP4 () const =0;
QPointF CutSpline ( qreal length, QPointF &spl1p2, QPointF &spl1p3, QPointF &spl2p2, QPointF &spl2p3) const;
protected:
virtual void CreateName() Q_DECL_OVERRIDE;
static qreal CalcSqDistance(qreal x1, qreal y1, qreal x2, qreal y2);
static void PointBezier_r(qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4,
qreal y4, qint16 level, QVector<qreal> &px, QVector<qreal> &py);
static QVector<QPointF> GetCubicBezierPoints(const QPointF &p1, const QPointF &p2, const QPointF &p3,
const QPointF &p4);
static qreal LengthBezier(const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4);
virtual QPointF GetControlPoint1() const =0;
virtual QPointF GetControlPoint2() const =0;
private:
qreal LengthT(qreal t) const;
};
#endif // VABSTRACTCUBICBEZIER_H

View file

@ -0,0 +1,159 @@
/************************************************************************
**
** @file vcubicbezier.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 8 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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 "vcubicbezier.h"
#include "vcubicbezier_p.h"
//---------------------------------------------------------------------------------------------------------------------
VCubicBezier::VCubicBezier()
: VAbstractCubicBezier(GOType::CubicBezier), d(new VCubicBezierData)
{
}
//---------------------------------------------------------------------------------------------------------------------
VCubicBezier::VCubicBezier(const VCubicBezier &curve)
: VAbstractCubicBezier(curve), d(curve.d)
{
}
//---------------------------------------------------------------------------------------------------------------------
VCubicBezier::VCubicBezier(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4, quint32 idObject,
Draw mode)
: VAbstractCubicBezier(GOType::CubicBezier, idObject, mode), d(new VCubicBezierData(p1, p2, p3, p4))
{
CreateName();
}
//---------------------------------------------------------------------------------------------------------------------
VCubicBezier &VCubicBezier::operator=(const VCubicBezier &curve)
{
if ( &curve == this )
{
return *this;
}
VAbstractCubicBezier::operator=(curve);
d = curve.d;
return *this;
}
//---------------------------------------------------------------------------------------------------------------------
VCubicBezier::~VCubicBezier()
{
}
//---------------------------------------------------------------------------------------------------------------------
VPointF VCubicBezier::GetP1() const
{
return d->p1;
}
//---------------------------------------------------------------------------------------------------------------------
void VCubicBezier::SetP1(const VPointF &p)
{
d->p1 = p;
}
//---------------------------------------------------------------------------------------------------------------------
VPointF VCubicBezier::GetP2() const
{
return d->p2;
}
//---------------------------------------------------------------------------------------------------------------------
void VCubicBezier::SetP2(const VPointF &p)
{
d->p2 = p;
}
//---------------------------------------------------------------------------------------------------------------------
VPointF VCubicBezier::GetP3() const
{
return d->p3;
}
//---------------------------------------------------------------------------------------------------------------------
void VCubicBezier::SetP3(const VPointF &p)
{
d->p3 = p;
}
//---------------------------------------------------------------------------------------------------------------------
VPointF VCubicBezier::GetP4() const
{
return d->p4;
}
//---------------------------------------------------------------------------------------------------------------------
void VCubicBezier::SetP4(const VPointF &p)
{
d->p4 = p;
}
//---------------------------------------------------------------------------------------------------------------------
qreal VCubicBezier::GetStartAngle() const
{
return QLineF(GetP1().toQPointF(), GetP2().toQPointF()).angle();
}
//---------------------------------------------------------------------------------------------------------------------
qreal VCubicBezier::GetEndAngle() const
{
return QLineF(GetP4().toQPointF(), GetP3().toQPointF()).angle();
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief GetLength return length of cubic bezier curve.
* @return length.
*/
qreal VCubicBezier::GetLength() const
{
return LengthBezier (GetP1().toQPointF(), GetP2().toQPointF(), GetP3().toQPointF(), GetP4().toQPointF());
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief GetPoints return list with cubic bezier curve points.
* @return list of points.
*/
QVector<QPointF> VCubicBezier::GetPoints() const
{
return GetCubicBezierPoints(GetP1().toQPointF(), GetP2().toQPointF(), GetP3().toQPointF(), GetP4().toQPointF());
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VCubicBezier::GetControlPoint1() const
{
return GetP2().toQPointF();
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VCubicBezier::GetControlPoint2() const
{
return GetP3().toQPointF();
}

View file

@ -0,0 +1,74 @@
/************************************************************************
**
** @file vcubicbezier.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 8 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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/>.
**
*************************************************************************/
#ifndef VCUBICBEZIER_H
#define VCUBICBEZIER_H
#include "vabstractcubicbezier.h"
#include "vpointf.h"
class VCubicBezierData;
class VCubicBezier : public VAbstractCubicBezier
{
public:
VCubicBezier();
VCubicBezier(const VCubicBezier &curve);
VCubicBezier(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4, quint32 idObject = 0,
Draw mode = Draw::Calculation);
VCubicBezier &operator=(const VCubicBezier &curve);
virtual ~VCubicBezier();
virtual VPointF GetP1() const Q_DECL_OVERRIDE;
void SetP1(const VPointF &p);
VPointF GetP2() const;
void SetP2(const VPointF &p);
VPointF GetP3() const;
void SetP3(const VPointF &p);
virtual VPointF GetP4() const Q_DECL_OVERRIDE;
void SetP4(const VPointF &p);
virtual qreal GetStartAngle() const Q_DECL_OVERRIDE;
virtual qreal GetEndAngle() const Q_DECL_OVERRIDE;
virtual qreal GetLength() const Q_DECL_OVERRIDE;
virtual QVector<QPointF> GetPoints() const Q_DECL_OVERRIDE;
protected:
virtual QPointF GetControlPoint1() const Q_DECL_OVERRIDE;
virtual QPointF GetControlPoint2() const Q_DECL_OVERRIDE;
private:
QSharedDataPointer<VCubicBezierData> d;
};
Q_DECLARE_TYPEINFO(VCubicBezier, Q_MOVABLE_TYPE);
#endif // VCUBICBEZIER_H

View file

@ -0,0 +1,105 @@
/************************************************************************
**
** @file vcubicbezier_p.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 8 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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/>.
**
*************************************************************************/
#ifndef VCUBICBEZIER_P_H
#define VCUBICBEZIER_P_H
#include <QSharedData>
#include <QLineF>
#include <QtCore/qmath.h>
#include "vpointf.h"
#include "../vmisc/vabstractapplication.h"
#ifdef Q_CC_GNU
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Weffc++"
#endif
class VCubicBezierData : public QSharedData
{
public:
VCubicBezierData();
VCubicBezierData(const VCubicBezierData &spline);
VCubicBezierData(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4);
virtual ~VCubicBezierData();
/** @brief p1 first spline point. */
VPointF p1;
/** @brief p2 fourth spline point. */
VPointF p2;
/** @brief p3 fourth spline point. */
VPointF p3;
/** @brief p4 fourth spline point. */
VPointF p4;
private:
VCubicBezierData &operator=(const VCubicBezierData &) Q_DECL_EQ_DELETE;
};
//---------------------------------------------------------------------------------------------------------------------
VCubicBezierData::VCubicBezierData()
: p1(),
p2(),
p3(),
p4()
{
}
//---------------------------------------------------------------------------------------------------------------------
VCubicBezierData::VCubicBezierData(const VCubicBezierData &curve)
: QSharedData(curve),
p1(curve.p1),
p2(curve.p2),
p3(curve.p3),
p4(curve.p4)
{
}
//---------------------------------------------------------------------------------------------------------------------
VCubicBezierData::VCubicBezierData(const VPointF &p1, const VPointF &p2, const VPointF &p3, const VPointF &p4)
: p1(p1),
p2(p2),
p3(p3),
p4(p4)
{
}
//---------------------------------------------------------------------------------------------------------------------
VCubicBezierData::~VCubicBezierData()
{
}
#ifdef Q_CC_GNU
#pragma GCC diagnostic pop
#endif
#endif // VCUBICBEZIER_P_H

View file

@ -9,7 +9,9 @@ SOURCES += \
$$PWD/vspline.cpp \
$$PWD/vsplinepath.cpp \
$$PWD/vsplinepoint.cpp \
$$PWD/vellipticalarc.cpp
$$PWD/vellipticalarc.cpp \
$$PWD/vcubicbezier.cpp \
$$PWD/vabstractcubicbezier.cpp
win32-msvc*:SOURCES += $$PWD/stable.cpp
@ -31,4 +33,7 @@ HEADERS += \
$$PWD/vgeometrydef.h \
$$PWD/vellipticalarc.h \
$$PWD/vellipticalarc_p.h \
$$PWD/vabstractcurve_p.h
$$PWD/vabstractcurve_p.h \
$$PWD/vcubicbezier.h \
$$PWD/vcubicbezier_p.h \
$$PWD/vabstractcubicbezier.h

View file

@ -32,7 +32,7 @@
#include <QString>
enum class Draw : char { Calculation, Modeling, Layout };
enum class GOType : char { Point, Arc, EllipticalArc, Spline, SplinePath, Unknown };
enum class GOType : char { Point, Arc, EllipticalArc, Spline, SplinePath, CubicBezier, Unknown };
enum class SplinePointPosition : char { FirstPoint, LastPoint };
#endif // VGEOMETRYDEF_H

View file

@ -32,12 +32,14 @@
#include <QPainterPath>
#include <QtCore/qmath.h>
#define M_2PI 6.28318530717958647692528676655900576
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VSpline default constructor
*/
VSpline::VSpline()
:VAbstractCurve(GOType::Spline), d(new VSplineData)
:VAbstractCubicBezier(GOType::Spline), d(new VSplineData)
{}
//---------------------------------------------------------------------------------------------------------------------
@ -46,7 +48,7 @@ VSpline::VSpline()
* @param spline spline from which the copy.
*/
VSpline::VSpline ( const VSpline & spline )
:VAbstractCurve(spline), d(spline.d)
:VAbstractCubicBezier(spline), d(spline.d)
{}
//---------------------------------------------------------------------------------------------------------------------
@ -62,7 +64,8 @@ VSpline::VSpline ( const VSpline & spline )
*/
VSpline::VSpline (VPointF p1, VPointF p4, qreal angle1, qreal angle2, qreal kAsm1, qreal kAsm2, qreal kCurve,
quint32 idObject, Draw mode)
:VAbstractCurve(GOType::Spline, idObject, mode), d(new VSplineData(p1, p4, angle1, angle2, kAsm1, kAsm2, kCurve))
: VAbstractCubicBezier(GOType::Spline, idObject, mode),
d(new VSplineData(p1, p4, angle1, angle2, kAsm1, kAsm2, kCurve))
{
CreateName();
}
@ -76,7 +79,7 @@ VSpline::VSpline (VPointF p1, VPointF p4, qreal angle1, qreal angle2, qreal kAsm
* @param p4 second point spline.
*/
VSpline::VSpline (VPointF p1, QPointF p2, QPointF p3, VPointF p4, quint32 idObject, Draw mode)
:VAbstractCurve(GOType::Spline, idObject, mode), d(new VSplineData(p1, p2, p3, p4))
:VAbstractCubicBezier(GOType::Spline, idObject, mode), d(new VSplineData(p1, p2, p3, p4))
{
CreateName();
}
@ -101,14 +104,13 @@ VSpline::VSpline (VPointF p1, QPointF p2, QPointF p3, VPointF p4, quint32 idObje
VSpline::VSpline(VPointF p1, VPointF p4, qreal angle1, const QString &angle1Formula, qreal angle2,
const QString &angle2Formula, qreal c1Length, const QString &c1LengthFormula, qreal c2Length,
const QString &c2LengthFormula, quint32 idObject, Draw mode)
: VAbstractCurve(GOType::Spline, idObject, mode),
: VAbstractCubicBezier(GOType::Spline, idObject, mode),
d(new VSplineData(p1, p4, angle1, angle1Formula, angle2,angle2Formula, c1Length, c1LengthFormula, c2Length,
c2LengthFormula))
{
CreateName();
}
//---------------------------------------------------------------------------------------------------------------------
VSpline::~VSpline()
{}
@ -123,111 +125,6 @@ qreal VSpline::GetLength () const
return LengthBezier ( GetP1().toQPointF(), GetP2(), GetP3(), GetP4().toQPointF());
}
//---------------------------------------------------------------------------------------------------------------------
qreal VSpline::LengthT(qreal t) const
{
if (t < 0 || t > 1)
{
qDebug()<<"Wrong value t.";
return 0;
}
QLineF seg1_2 ( GetP1 ().toQPointF(), GetP2 () );
seg1_2.setLength(seg1_2.length () * t);
QPointF p12 = seg1_2.p2();
QLineF seg2_3 ( GetP2 (), GetP3 () );
seg2_3.setLength(seg2_3.length () * t);
QPointF p23 = seg2_3.p2();
QLineF seg12_23 ( p12, p23 );
seg12_23.setLength(seg12_23.length () * t);
QPointF p123 = seg12_23.p2();
QLineF seg3_4 ( GetP3 (), GetP4 ().toQPointF() );
seg3_4.setLength(seg3_4.length () * t);
QPointF p34 = seg3_4.p2();
QLineF seg23_34 ( p23, p34 );
seg23_34.setLength(seg23_34.length () * t);
QPointF p234 = seg23_34.p2();
QLineF seg123_234 ( p123, p234 );
seg123_234.setLength(seg123_234.length () * t);
QPointF p1234 = seg123_234.p2();
return LengthBezier ( GetP1().toQPointF(), p12, p123, p1234);
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief CutSpline cut spline. GetPointP1() of base spline will return first point for first spline, GetPointP4()
* of base spline will return forth point of second spline.
* @param length length first spline
* @param spl1p2 second point of first spline
* @param spl1p3 third point of first spline
* @param spl2p2 second point of second spline
* @param spl2p3 third point of second spline
* @return point of cutting. This point is forth point of first spline and first point of second spline.
*/
QPointF VSpline::CutSpline ( qreal length, QPointF &spl1p2, QPointF &spl1p3, QPointF &spl2p2, QPointF &spl2p3 ) const
{
//Always need return two splines, so we must correct wrong length.
if (length < GetLength()*0.02)
{
length = GetLength()*0.02;
}
else if ( length > GetLength()*0.98)
{
length = GetLength()*0.98;
}
// Very stupid way find correct value of t.
// Better first compare with t = 0.5. Find length of spline.
// If length larger, take t = 0.75 and so on.
// If length less, take t = 0.25 and so on.
qreal parT = 0;
qreal step = 0.001;
while (1)
{
parT = parT + step;
qreal splLength = LengthT(parT);
if (splLength >= length || parT > 1)
{
break;
}
}
QLineF seg1_2 ( GetP1 ().toQPointF(), GetP2 () );
seg1_2.setLength(seg1_2.length () * parT);
QPointF p12 = seg1_2.p2();
QLineF seg2_3 ( GetP2 (), GetP3 () );
seg2_3.setLength(seg2_3.length () * parT);
QPointF p23 = seg2_3.p2();
QLineF seg12_23 ( p12, p23 );
seg12_23.setLength(seg12_23.length () * parT);
QPointF p123 = seg12_23.p2();
QLineF seg3_4 ( GetP3 (), GetP4 ().toQPointF() );
seg3_4.setLength(seg3_4.length () * parT);
QPointF p34 = seg3_4.p2();
QLineF seg23_34 ( p23, p34 );
seg23_34.setLength(seg23_34.length () * parT);
QPointF p234 = seg23_34.p2();
QLineF seg123_234 ( p123, p234 );
seg123_234.setLength(seg123_234.length () * parT);
QPointF p1234 = seg123_234.p2();
spl1p2 = p12;
spl1p3 = p123;
spl2p2 = p234;
spl2p3 = p34;
return p1234;
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VSpline::CutSpline(qreal length, VSpline &spl1, VSpline &spl2) const
{
@ -235,7 +132,7 @@ QPointF VSpline::CutSpline(qreal length, VSpline &spl1, VSpline &spl2) const
QPointF spl1p3;
QPointF spl2p2;
QPointF spl2p3;
QPointF cutPoint = CutSpline (length, spl1p2, spl1p3, spl2p2, spl2p3 );
const QPointF cutPoint = CutSpline (length, spl1p2, spl1p3, spl2p2, spl2p3 );
spl1 = VSpline(GetP1(), spl1p2, spl1p3, cutPoint);
spl2 = VSpline(cutPoint, spl2p2, spl2p3, GetP4());
@ -249,391 +146,7 @@ QPointF VSpline::CutSpline(qreal length, VSpline &spl1, VSpline &spl2) const
*/
QVector<QPointF> VSpline::GetPoints () const
{
return GetPoints(GetP1().toQPointF(), GetP2(), GetP3(), GetP4().toQPointF());
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief GetPoints return list with spline points.
* @param p1 first spline point.
* @param p2 first control point.
* @param p3 second control point.
* @param p4 last spline point.
* @return list of points.
*/
QVector<QPointF> VSpline::GetPoints (const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4)
{
QVector<QPointF> pvector;
QVector<qreal> x;
QVector<qreal> y;
QVector<qreal>& wx = x;
QVector<qreal>& wy = y;
x.append ( p1.x () );
y.append ( p1.y () );
PointBezier_r ( p1.x (), p1.y (), p2.x (), p2.y (),
p3.x (), p3.y (), p4.x (), p4.y (), 0, wx, wy );
x.append ( p4.x () );
y.append ( p4.y () );
for ( qint32 i = 0; i < x.count(); ++i )
{
pvector.append( QPointF ( x.at(i), y.at(i)) );
}
return pvector;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief LengthBezier return spline length using 4 spline point.
* @param p1 first spline point
* @param p2 first control point.
* @param p3 second control point.
* @param p4 last spline point.
* @return length.
*/
qreal VSpline::LengthBezier ( const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4 )
{
QPainterPath splinePath;
QVector<QPointF> points = GetPoints (p1, p2, p3, p4);
splinePath.moveTo(points.at(0));
for (qint32 i = 1; i < points.count(); ++i)
{
splinePath.lineTo(points.at(i));
}
return splinePath.length();
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief PointBezier_r find spline point using four point of spline.
* @param x1 х coordinate first point.
* @param y1 у coordinate first point.
* @param x2 х coordinate first control point.
* @param y2 у coordinate first control point.
* @param x3 х coordinate second control point.
* @param y3 у coordinate second control point.
* @param x4 х coordinate last point.
* @param y4 у coordinate last point.
* @param level level of recursion. In the begin 0.
* @param px list х coordinat spline points.
* @param py list у coordinat spline points.
*/
void VSpline::PointBezier_r ( qreal x1, qreal y1, qreal x2, qreal y2,
qreal x3, qreal y3, qreal x4, qreal y4,
qint16 level, QVector<qreal> &px, QVector<qreal> &py)
{
if (px.size() >= 2)
{
for (int i=1; i < px.size(); ++i)
{
if (QPointF(px.at(i-1), py.at(i-1)) == QPointF(px.at(i), py.at(i)))
{
qDebug("All neighbors points in path must be unique.");
}
}
}
const double curve_collinearity_epsilon = 1e-30;
const double curve_angle_tolerance_epsilon = 0.01;
const double m_angle_tolerance = 0.0;
enum curve_recursion_limit_e { curve_recursion_limit = 32 };
const double m_cusp_limit = 0.0;
double m_approximation_scale = 1.0;
double m_distance_tolerance_square;
m_distance_tolerance_square = 0.5 / m_approximation_scale;
m_distance_tolerance_square *= m_distance_tolerance_square;
if (level > curve_recursion_limit)
{
return;
}
// Calculate all the mid-points of the line segments
//----------------------
const double x12 = (x1 + x2) / 2;
const double y12 = (y1 + y2) / 2;
const double x23 = (x2 + x3) / 2;
const double y23 = (y2 + y3) / 2;
const double x34 = (x3 + x4) / 2;
const double y34 = (y3 + y4) / 2;
const double x123 = (x12 + x23) / 2;
const double y123 = (y12 + y23) / 2;
const double x234 = (x23 + x34) / 2;
const double y234 = (y23 + y34) / 2;
const double x1234 = (x123 + x234) / 2;
const double y1234 = (y123 + y234) / 2;
// Try to approximate the full cubic curve by a single straight line
//------------------
const double dx = x4-x1;
const double dy = y4-y1;
double d2 = fabs((x2 - x4) * dy - (y2 - y4) * dx);
double d3 = fabs((x3 - x4) * dy - (y3 - y4) * dx);
switch ((static_cast<int>(d2 > curve_collinearity_epsilon) << 1) +
static_cast<int>(d3 > curve_collinearity_epsilon))
{
case 0:
{
// All collinear OR p1==p4
//----------------------
double k = dx*dx + dy*dy;
if (k < 0.000000001)
{
d2 = CalcSqDistance(x1, y1, x2, y2);
d3 = CalcSqDistance(x4, y4, x3, y3);
}
else
{
k = 1 / k;
{
const double da1 = x2 - x1;
const double da2 = y2 - y1;
d2 = k * (da1*dx + da2*dy);
}
{
const double da1 = x3 - x1;
const double da2 = y3 - y1;
d3 = k * (da1*dx + da2*dy);
}
if (d2 > 0 && d2 < 1 && d3 > 0 && d3 < 1)
{
// Simple collinear case, 1---2---3---4
// We can leave just two endpoints
return;
}
if (d2 <= 0)
{
d2 = CalcSqDistance(x2, y2, x1, y1);
}
else if (d2 >= 1)
{
d2 = CalcSqDistance(x2, y2, x4, y4);
}
else
{
d2 = CalcSqDistance(x2, y2, x1 + d2*dx, y1 + d2*dy);
}
if (d3 <= 0)
{
d3 = CalcSqDistance(x3, y3, x1, y1);
}
else if (d3 >= 1)
{
d3 = CalcSqDistance(x3, y3, x4, y4);
}
else
{
d3 = CalcSqDistance(x3, y3, x1 + d3*dx, y1 + d3*dy);
}
}
if (d2 > d3)
{
if (d2 < m_distance_tolerance_square)
{
px.append(x2);
py.append(y2);
return;
}
}
else
{
if (d3 < m_distance_tolerance_square)
{
px.append(x3);
py.append(y3);
return;
}
}
break;
}
case 1:
{
// p1,p2,p4 are collinear, p3 is significant
//----------------------
if (d3 * d3 <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
if (m_angle_tolerance < curve_angle_tolerance_epsilon)
{
px.append(x23);
py.append(y23);
return;
}
// Angle Condition
//----------------------
double da1 = fabs(atan2(y4 - y3, x4 - x3) - atan2(y3 - y2, x3 - x2));
if (da1 >= M_PI)
{
da1 = 2*M_PI - da1;
}
if (da1 < m_angle_tolerance)
{
px.append(x2);
py.append(y2);
px.append(x3);
py.append(y3);
return;
}
if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0)
{
if (da1 > m_cusp_limit)
{
px.append(x3);
py.append(y3);
return;
}
}
}
break;
}
case 2:
{
// p1,p3,p4 are collinear, p2 is significant
//----------------------
if (d2 * d2 <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
if (m_angle_tolerance < curve_angle_tolerance_epsilon)
{
px.append(x23);
py.append(y23);
return;
}
// Angle Condition
//----------------------
double da1 = fabs(atan2(y3 - y2, x3 - x2) - atan2(y2 - y1, x2 - x1));
if (da1 >= M_PI)
{
da1 = 2*M_PI - da1;
}
if (da1 < m_angle_tolerance)
{
px.append(x2);
py.append(y2);
px.append(x3);
py.append(y3);
return;
}
if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0)
{
if (da1 > m_cusp_limit)
{
px.append(x2);
py.append(y2);
return;
}
}
}
break;
}
case 3:
{
// Regular case
//-----------------
if ((d2 + d3)*(d2 + d3) <= m_distance_tolerance_square * (dx*dx + dy*dy))
{
// If the curvature doesn't exceed the distance_tolerance value
// we tend to finish subdivisions.
//----------------------
if (m_angle_tolerance < curve_angle_tolerance_epsilon)
{
px.append(x23);
py.append(y23);
return;
}
// Angle & Cusp Condition
//----------------------
const double k = atan2(y3 - y2, x3 - x2);
double da1 = fabs(k - atan2(y2 - y1, x2 - x1));
double da2 = fabs(atan2(y4 - y3, x4 - x3) - k);
if (da1 >= M_PI)
{
da1 = 2*M_PI - da1;
}
if (da2 >= M_PI)
{
da2 = 2*M_PI - da2;
}
if (da1 + da2 < m_angle_tolerance)
{
// Finally we can stop the recursion
//----------------------
px.append(x23);
py.append(y23);
return;
}
if (m_cusp_limit > 0.0 || m_cusp_limit < 0.0)
{
if (da1 > m_cusp_limit)
{
px.append(x2);
py.append(y2);
return;
}
if (da2 > m_cusp_limit)
{
px.append(x3);
py.append(y3);
return;
}
}
}
break;
}
default:
break;
}
// Continue subdivision
//----------------------
PointBezier_r(x1, y1, x12, y12, x123, y123, x1234, y1234, static_cast<qint16>(level + 1), px, py);
PointBezier_r(x1234, y1234, x234, y234, x34, y34, x4, y4, static_cast<qint16>(level + 1), px, py);
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief CalcSqDistance calculate squared distance.
* @param x1 х coordinate first point.
* @param y1 у coordinate first point.
* @param x2 х coordinate second point.
* @param y2 у coordinate second point.
* @return squared length.
*/
qreal VSpline::CalcSqDistance (qreal x1, qreal y1, qreal x2, qreal y2)
{
const qreal dx = x2 - x1;
const qreal dy = y2 - y1;
return dx * dx + dy * dy;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief CreateName create spline name.
*/
void VSpline::CreateName()
{
QString name = SPL_ + QString("%1_%2").arg(this->GetP1().name()).arg(this->GetP4().name());
if (GetDuplicate() > 0)
{
name += QString("_%1").arg(GetDuplicate());
}
setName(name);
return GetCubicBezierPoints(GetP1().toQPointF(), GetP2(), GetP3(), GetP4().toQPointF());
}
//---------------------------------------------------------------------------------------------------------------------
@ -663,7 +176,7 @@ QVector<QPointF> VSpline::SplinePoints(const QPointF &p1, const QPointF &p4, qre
p4p3.setAngle(angle2);
QPointF p2 = p1p2.p2();
QPointF p3 = p4p3.p2();
return GetPoints(p1, p2, p3, p4);
return GetCubicBezierPoints(p1, p2, p3, p4);
}
//---------------------------------------------------------------------------------------------------------------------
@ -673,7 +186,7 @@ VSpline &VSpline::operator =(const VSpline &spline)
{
return *this;
}
VAbstractCurve::operator=(spline);
VAbstractCubicBezier::operator=(spline);
d = spline.d;
return *this;
}
@ -980,3 +493,15 @@ qreal VSpline::ParamT (const QPointF &pBt) const
return tx;
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VSpline::GetControlPoint1() const
{
return GetP2 ();
}
//---------------------------------------------------------------------------------------------------------------------
QPointF VSpline::GetControlPoint2() const
{
return GetP3 ();
}

View file

@ -29,7 +29,7 @@
#ifndef VSPLINE_H
#define VSPLINE_H
#include "vabstractcurve.h"
#include "vabstractcubicbezier.h"
#include "vpointf.h"
#include <QLineF>
#include <QPointF>
@ -37,12 +37,10 @@
class QPainterPath;
class VSplineData;
#define M_2PI 6.28318530717958647692528676655900576
/**
* @brief VSpline class that implements the spline.
*/
class VSpline :public VAbstractCurve
class VSpline :public VAbstractCubicBezier
{
public:
VSpline();
@ -54,17 +52,17 @@ public:
VSpline (VPointF p1, VPointF p4, qreal angle1, const QString &angle1Formula, qreal angle2,
const QString &angle2Formula, qreal c1Length, const QString &c1LengthFormula, qreal c2Length,
const QString &c2LengthFormula, quint32 idObject = 0, Draw mode = Draw::Calculation);
virtual ~VSpline() Q_DECL_OVERRIDE;
virtual ~VSpline();
VSpline &operator=(const VSpline &spl);
VPointF GetP1 () const;
void SetP1 (const VPointF &p);
virtual VPointF GetP1 () const Q_DECL_OVERRIDE;
void SetP1 (const VPointF &p);
QPointF GetP2 () const;
QPointF GetP3 () const;
VPointF GetP4 () const;
void SetP4 (const VPointF &p);
virtual VPointF GetP4 () const Q_DECL_OVERRIDE;
void SetP4 (const VPointF &p);
virtual qreal GetStartAngle () const Q_DECL_OVERRIDE;
virtual qreal GetEndAngle() const Q_DECL_OVERRIDE;
@ -84,27 +82,25 @@ public:
void SetC1Length(qreal length, const QString &formula);
void SetC2Length(qreal length, const QString &formula);
qreal GetLength () const;
virtual qreal GetLength () const Q_DECL_OVERRIDE;
qreal GetKasm1() const;
qreal GetKasm2() const;
qreal GetKcurve() const;
qreal LengthT(qreal t) const;
QPointF CutSpline ( qreal length, QPointF &spl1p2, QPointF &spl1p3, QPointF &spl2p2, QPointF &spl2p3) const;
using VAbstractCubicBezier::CutSpline;
QPointF CutSpline ( qreal length, VSpline &spl1, VSpline &spl2) const;
QVector<QPointF> GetPoints () const;
virtual QVector<QPointF> GetPoints () const Q_DECL_OVERRIDE;
// cppcheck-suppress unusedFunction
static QVector<QPointF> SplinePoints(const QPointF &p1, const QPointF &p4, qreal angle1, qreal angle2, qreal kAsm1,
qreal kAsm2, qreal kCurve);
qreal ParamT(const QPointF &pBt) const;
protected:
static QVector<QPointF> GetPoints (const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4 );
virtual void CreateName() Q_DECL_OVERRIDE;
virtual QPointF GetControlPoint1() const Q_DECL_OVERRIDE;
virtual QPointF GetControlPoint2() const Q_DECL_OVERRIDE;
private:
QSharedDataPointer<VSplineData> d;
static qreal LengthBezier (const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4 );
static void PointBezier_r ( qreal x1, qreal y1, qreal x2, qreal y2, qreal x3, qreal y3, qreal x4, qreal y4,
qint16 level, QVector<qreal> &px, QVector<qreal> &py);
static qreal CalcSqDistance ( qreal x1, qreal y1, qreal x2, qreal y2);
QVector<qreal> CalcT(qreal curveCoord1, qreal curveCoord2, qreal curveCoord3, qreal curveCoord4,
qreal pointCoord) const;
static qint32 Cubic(QVector<qreal> &x, qreal a, qreal b, qreal c);

View file

@ -74,6 +74,7 @@ enum class Tool : ToolVisHolderType
Bisector,
LineIntersect,
Spline,
CubicBezier,
CutSpline,
CutArc,
Arc,
@ -127,6 +128,7 @@ enum class Vis : ToolVisHolderType
ToolPointFromArcAndTangent,
ToolShoulderPoint,
ToolSpline,
ToolCubicBezier,
ToolTriangle,
ToolCutSpline,
ToolSplinePath,

View file

@ -34,7 +34,8 @@ HEADERS += \
$$PWD/support/dialogeditwrongformula.h \
$$PWD/support/dialogundo.h \
$$PWD/tools/dialogtruedarts.h \
$$PWD/tools/dialogpointofintersectioncurves.h
$$PWD/tools/dialogpointofintersectioncurves.h \
$$PWD/tools/dialogcubicbezier.h
SOURCES += \
$$PWD/tools/dialogalongline.cpp \
@ -68,7 +69,8 @@ SOURCES += \
$$PWD/support/dialogeditwrongformula.cpp \
$$PWD/support/dialogundo.cpp \
$$PWD/tools/dialogtruedarts.cpp \
$$PWD/tools/dialogpointofintersectioncurves.cpp
$$PWD/tools/dialogpointofintersectioncurves.cpp \
$$PWD/tools/dialogcubicbezier.cpp
FORMS += \
$$PWD/tools/dialogalongline.ui \
@ -101,4 +103,5 @@ FORMS += \
$$PWD/support/dialogeditwrongformula.ui \
$$PWD/support/dialogundo.ui \
$$PWD/tools/dialogtruedarts.ui \
$$PWD/tools/dialogpointofintersectioncurves.ui
$$PWD/tools/dialogpointofintersectioncurves.ui \
$$PWD/tools/dialogcubicbezier.ui

View file

@ -42,6 +42,7 @@
#include "dialogs/tools/dialogshoulderpoint.h"
#include "dialogs/tools/dialogsinglepoint.h"
#include "dialogs/tools/dialogspline.h"
#include "dialogs/tools/dialogcubicbezier.h"
#include "dialogs/tools/dialogsplinepath.h"
#include "dialogs/tools/dialogheight.h"
#include "dialogs/tools/dialogcutarc.h"

View file

@ -0,0 +1,261 @@
/************************************************************************
**
** @file dialogcubicbezier.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 10 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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 "dialogcubicbezier.h"
#include "ui_dialogcubicbezier.h"
#include "../../visualization/vistoolcubicbezier.h"
//---------------------------------------------------------------------------------------------------------------------
DialogCubicBezier::DialogCubicBezier(const VContainer *data, const quint32 &toolId, QWidget *parent)
: DialogTool(data, toolId, parent),
ui(new Ui::DialogCubicBezier),
spl(),
newDuplicate(-1)
{
ui->setupUi(this);
InitOkCancelApply(ui);
FillComboBoxPoints(ui->comboBoxP1);
FillComboBoxPoints(ui->comboBoxP2);
FillComboBoxPoints(ui->comboBoxP3);
FillComboBoxPoints(ui->comboBoxP4);
FillComboBoxLineColors(ui->comboBoxColor);
CheckState();
connect(ui->comboBoxP1, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
this, &DialogCubicBezier::PointNameChanged);
connect(ui->comboBoxP2, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
this, &DialogCubicBezier::PointNameChanged);
connect(ui->comboBoxP3, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
this, &DialogCubicBezier::PointNameChanged);
connect(ui->comboBoxP4, static_cast<void (QComboBox::*)(const QString &)>(&QComboBox::currentIndexChanged),
this, &DialogCubicBezier::PointNameChanged);
vis = new VisToolCubicBezier(data);
}
//---------------------------------------------------------------------------------------------------------------------
DialogCubicBezier::~DialogCubicBezier()
{
DeleteVisualization<VisToolCubicBezier>();
delete ui;
}
//---------------------------------------------------------------------------------------------------------------------
VCubicBezier DialogCubicBezier::GetSpline() const
{
return spl;
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezier::SetSpline(const VCubicBezier &spline)
{
spl = spline;
setCurrentPointId(ui->comboBoxP1, spl.GetP1().id());
setCurrentPointId(ui->comboBoxP2, spl.GetP2().id());
setCurrentPointId(ui->comboBoxP3, spl.GetP3().id());
setCurrentPointId(ui->comboBoxP4, spl.GetP4().id());
ui->lineEditSplineName->setText(spl.name());
auto path = qobject_cast<VisToolCubicBezier *>(vis);
SCASSERT(path != nullptr);
path->setObject1Id(spl.GetP1().id());
path->setObject2Id(spl.GetP2().id());
path->setObject3Id(spl.GetP3().id());
path->setObject4Id(spl.GetP4().id());
}
//---------------------------------------------------------------------------------------------------------------------
QString DialogCubicBezier::GetColor() const
{
return GetComboBoxCurrentData(ui->comboBoxColor);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezier::SetColor(const QString &value)
{
ChangeCurrentData(ui->comboBoxColor, value);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezier::ChosenObject(quint32 id, const SceneObject &type)
{
if (prepare == false)// After first choose we ignore all objects
{
if (type == SceneObject::Point)
{
auto *path = qobject_cast<VisToolCubicBezier *>(vis);
SCASSERT(path != nullptr);
switch (number)
{
case 0:
if (SetObject(id, ui->comboBoxP1, tr("Select the second point of curve")))
{
++number;
path->VisualMode(id);
}
break;
case 1:
if (SetObject(id, ui->comboBoxP2, tr("Select the third point of curve")))
{
++number;
path->setObject2Id(id);
path->RefreshGeometry();
}
break;
case 2:
if (SetObject(id, ui->comboBoxP3, tr("Select the fourth point of curve")))
{
++number;
path->setObject3Id(id);
path->RefreshGeometry();
}
break;
case 3:
if (getCurrentObjectId(ui->comboBoxP1) != id)
{
if (SetObject(id, ui->comboBoxP4, ""))
{
++number;
path->setObject4Id(id);
path->RefreshGeometry();
prepare = true;
DialogAccepted();
}
}
break;
default:
break;
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezier::PointNameChanged()
{
QColor color = okColor;
if (getCurrentObjectId(ui->comboBoxP1) == getCurrentObjectId(ui->comboBoxP4))
{
flagError = false;
color = errorColor;
ui->lineEditSplineName->setText(tr("Invalid spline"));
}
else
{
flagError = true;
color = okColor;
if (getCurrentObjectId(ui->comboBoxP1) == spl.GetP1().id() &&
getCurrentObjectId(ui->comboBoxP4) == spl.GetP4().id())
{
newDuplicate = -1;
ui->lineEditSplineName->setText(spl.name());
}
else
{
VCubicBezier spline(*GetP1(), *GetP2(), *GetP3(), *GetP4());
if (not data->IsUnique(spline.name()))
{
newDuplicate = DNumber(spline.name());
spline.SetDuplicate(newDuplicate);
}
ui->lineEditSplineName->setText(spline.name());
}
}
ChangeColor(ui->labelName, color);
ChangeColor(ui->labelFirstPoint, color);
ChangeColor(ui->labelSecondPoint, color);
ChangeColor(ui->labelThirdPoint, color);
ChangeColor(ui->labelForthPoint, color);
CheckState();
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezier::ShowVisualization()
{
AddVisualization<VisToolCubicBezier>();
}
//---------------------------------------------------------------------------------------------------------------------
void DialogCubicBezier::SaveData()
{
const auto p1 = GetP1();
const auto p2 = GetP2();
const auto p3 = GetP3();
const auto p4 = GetP4();
spl = VCubicBezier(*p1, *p2, *p3, *p4);
const quint32 d = spl.GetDuplicate();//Save previous value
newDuplicate <= -1 ? spl.SetDuplicate(d) : spl.SetDuplicate(static_cast<quint32>(newDuplicate));
auto path = qobject_cast<VisToolCubicBezier *>(vis);
SCASSERT(path != nullptr);
path->setObject1Id(p1->id());
path->setObject2Id(p2->id());
path->setObject3Id(p3->id());
path->setObject4Id(p4->id());
path->SetMode(Mode::Show);
path->RefreshGeometry();
}
//---------------------------------------------------------------------------------------------------------------------
const QSharedPointer<VPointF> DialogCubicBezier::GetP1() const
{
return data->GeometricObject<VPointF>(getCurrentObjectId(ui->comboBoxP1));
}
//---------------------------------------------------------------------------------------------------------------------
const QSharedPointer<VPointF> DialogCubicBezier::GetP2() const
{
return data->GeometricObject<VPointF>(getCurrentObjectId(ui->comboBoxP2));
}
//---------------------------------------------------------------------------------------------------------------------
const QSharedPointer<VPointF> DialogCubicBezier::GetP3() const
{
return data->GeometricObject<VPointF>(getCurrentObjectId(ui->comboBoxP3));
}
//---------------------------------------------------------------------------------------------------------------------
const QSharedPointer<VPointF> DialogCubicBezier::GetP4() const
{
return data->GeometricObject<VPointF>(getCurrentObjectId(ui->comboBoxP4));
}

View file

@ -0,0 +1,77 @@
/************************************************************************
**
** @file dialogcubicbezier.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 10 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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/>.
**
*************************************************************************/
#ifndef DIALOGCUBICBEZIER_H
#define DIALOGCUBICBEZIER_H
#include "dialogtool.h"
#include "../vgeometry/vcubicbezier.h"
namespace Ui
{
class DialogCubicBezier;
}
class DialogCubicBezier : public DialogTool
{
Q_OBJECT
public:
explicit DialogCubicBezier(const VContainer *data, const quint32 &toolId, QWidget *parent = nullptr);
virtual ~DialogCubicBezier();
VCubicBezier GetSpline() const;
void SetSpline(const VCubicBezier &spline);
QString GetColor() const;
void SetColor(const QString &value);
public slots:
virtual void ChosenObject(quint32 id, const SceneObject &type) Q_DECL_OVERRIDE;
virtual void PointNameChanged() Q_DECL_OVERRIDE;
protected:
virtual void ShowVisualization() Q_DECL_OVERRIDE;
/**
* @brief SaveData Put dialog data in local variables
*/
virtual void SaveData() Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(DialogCubicBezier)
Ui::DialogCubicBezier *ui;
/** @brief spl spline */
VCubicBezier spl;
qint32 newDuplicate;
const QSharedPointer<VPointF> GetP1() const;
const QSharedPointer<VPointF> GetP2() const;
const QSharedPointer<VPointF> GetP3() const;
const QSharedPointer<VPointF> GetP4() const;
};
#endif // DIALOGCUBICBEZIER_H

View file

@ -0,0 +1,148 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DialogCubicBezier</class>
<widget class="QDialog" name="DialogCubicBezier">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>285</width>
<height>245</height>
</rect>
</property>
<property name="windowTitle">
<string>Cubic bezier</string>
</property>
<property name="windowIcon">
<iconset resource="../../../vmisc/share/resources/icon.qrc">
<normaloff>:/icon/64x64/icon64x64.png</normaloff>:/icon/64x64/icon64x64.png</iconset>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::ExpandingFieldsGrow</enum>
</property>
<item row="4" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Color:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QComboBox" name="comboBoxColor">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="labelName">
<property name="text">
<string>Name:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QLineEdit" name="lineEditSplineName">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="labelFirstPoint">
<property name="text">
<string>First point:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="comboBoxP1"/>
</item>
<item row="1" column="0">
<widget class="QLabel" name="labelSecondPoint">
<property name="text">
<string>Second point:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QComboBox" name="comboBoxP2"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="labelThirdPoint">
<property name="text">
<string>Third point:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QComboBox" name="comboBoxP3"/>
</item>
<item row="3" column="0">
<widget class="QLabel" name="labelForthPoint">
<property name="text">
<string>Fourth point:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboBoxP4"/>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources>
<include location="../../../vmisc/share/resources/icon.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DialogCubicBezier</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DialogCubicBezier</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View file

@ -61,7 +61,7 @@ DialogCutSpline::DialogCutSpline(const VContainer *data, const quint32 &toolId,
flagFormula = false;
CheckState();
FillComboBoxSplines(ui->comboBoxSpline, FillComboBox::NoChildren, ch1, ch2);
FillComboBoxSimpleSplines(ui->comboBoxSpline, FillComboBox::NoChildren, ch1, ch2);
FillComboBoxLineColors(ui->comboBoxColor);
connect(ui->toolButtonExprLength, &QPushButton::clicked, this, &DialogCutSpline::FXLength);

View file

@ -128,27 +128,91 @@ void DialogTool::FillComboBoxPoints(QComboBox *box, FillComboBox rule, const qui
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxArcs(QComboBox *box, FillComboBox rule, const quint32 &ch1, const quint32 &ch2) const
{
FillCombo<VArc>(box, GOType::Arc, rule, ch1, ch2);
FillCombo<VAbstractCurve>(box, GOType::Arc, rule, ch1, ch2);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxSplines(QComboBox *box, FillComboBox rule, const quint32 &ch1, const quint32 &ch2) const
{
FillCombo<VSpline>(box, GOType::Spline, rule, ch1, ch2);
FillCombo<VAbstractCurve>(box, GOType::Spline, rule, ch1, ch2);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxSplinesPath(QComboBox *box, FillComboBox rule, const quint32 &ch1,
const quint32 &ch2) const
{
FillCombo<VSplinePath>(box, GOType::SplinePath, rule, ch1, ch2);
FillCombo<VAbstractCurve>(box, GOType::SplinePath, rule, ch1, ch2);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxSimpleSplines(QComboBox *box, FillComboBox rule, const quint32 &ch1,
const quint32 &ch2) const
{
SCASSERT(box != nullptr);
box->blockSignals(true);
const auto objs = data->DataGObjects();
QHash<quint32, QSharedPointer<VGObject> >::const_iterator i;
QMap<QString, quint32> list;
for (i = objs->constBegin(); i != objs->constEnd(); ++i)
{
if (rule == FillComboBox::NoChildren)
{
if (i.key() != toolId && i.key() != ch1 && i.key() != ch2)
{
QSharedPointer<VGObject> obj = i.value();
if ((obj->getType() == GOType::Spline || obj->getType() == GOType::CubicBezier) &&
obj->getMode() == Draw::Calculation)
{
const auto curve = data->GeometricObject<VAbstractCurve>(i.key());
QString newName = curve->name();
int bias = 0;
if (qApp->TrVars()->VariablesToUser(newName, 0, curve->name(), bias))
{
list[newName] = i.key();
}
else
{
list[curve->name()] = i.key();
}
}
}
}
else
{
if (i.key() != toolId)
{
QSharedPointer<VGObject> obj = i.value();
if ((obj->getType() == GOType::Spline || obj->getType() == GOType::CubicBezier) &&
obj->getMode() == Draw::Calculation)
{
const auto curve = data->GeometricObject<VAbstractCurve>(i.key());
QString newName = curve->name();
int bias = 0;
if (qApp->TrVars()->VariablesToUser(newName, 0, curve->name(), bias))
{
list[newName] = i.key();
}
else
{
list[curve->name()] = i.key();
}
}
}
}
}
FillList(box, list);
box->blockSignals(false);
}
//---------------------------------------------------------------------------------------------------------------------
void DialogTool::FillComboBoxCurves(QComboBox *box) const
{
SCASSERT(box != nullptr);
const QHash<quint32, QSharedPointer<VGObject> > *objs = data->DataGObjects();
const auto objs = data->DataGObjects();
QMap<QString, quint32> list;
QHash<quint32, QSharedPointer<VGObject> >::const_iterator i;
for (i = objs->constBegin(); i != objs->constEnd(); ++i)
@ -157,9 +221,10 @@ void DialogTool::FillComboBoxCurves(QComboBox *box) const
{
QSharedPointer<VGObject> obj = i.value();
if ((obj->getType() == GOType::Arc || obj->getType() == GOType::Spline ||
obj->getType() == GOType::SplinePath) && obj->getMode() == Draw::Calculation)
obj->getType() == GOType::SplinePath || obj->getType() == GOType::CubicBezier) &&
obj->getMode() == Draw::Calculation)
{
const QSharedPointer<VAbstractCurve> curve = data->GeometricObject<VAbstractCurve>(i.key());
const auto curve = data->GeometricObject<VAbstractCurve>(i.key());
QString newName = curve->name();
int bias = 0;

View file

@ -192,6 +192,8 @@ protected:
const quint32 &ch1 = NULL_ID, const quint32 &ch2 = NULL_ID)const;
void FillComboBoxSplinesPath(QComboBox *box, FillComboBox rule = FillComboBox::Whole,
const quint32 &ch1 = NULL_ID, const quint32 &ch2 = NULL_ID)const;
void FillComboBoxSimpleSplines(QComboBox *box, FillComboBox rule = FillComboBox::Whole,
const quint32 &ch1 = NULL_ID, const quint32 &ch2 = NULL_ID)const;
void FillComboBoxCurves(QComboBox *box)const;
void FillComboBoxTypeLine(QComboBox *box, const QMap<QString, QIcon> &stylesPics) const;
void FillComboBoxLineColors(QComboBox *box)const;

View file

@ -40,6 +40,7 @@
#include "toolcurve/vtoolarc.h"
#include "toolcurve/vtoolarcwithlength.h"
#include "toolcurve/vtoolspline.h"
#include "toolcurve/vtoolcubicbezier.h"
#include "toolcurve/vtoolsplinepath.h"
#include "vtoolline.h"
#include "toolpoint/toolsinglepoint/toolcut/vtoolcutspline.h"

View file

@ -0,0 +1,252 @@
/************************************************************************
**
** @file vtoolcubicbezier.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 10 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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 "vtoolcubicbezier.h"
#include "../vgeometry/vcubicbezier.h"
#include "../../../dialogs/tools/dialogcubicbezier.h"
#include "../../../undocommands/movespline.h"
#include "../../../visualization/vistoolcubicbezier.h"
const QString VToolCubicBezier::ToolType = QStringLiteral("cubicBezier");
//---------------------------------------------------------------------------------------------------------------------
VToolCubicBezier::VToolCubicBezier(VAbstractPattern *doc, VContainer *data, quint32 id, const QString &color,
const Source &typeCreation, QGraphicsItem *parent)
:VAbstractSpline(doc, data, id, parent)
{
sceneType = SceneObject::Spline;
lineColor = color;
this->setPen(QPen(Qt::black, qApp->toPixel(WidthHairLine(*VAbstractTool::data.GetPatternUnit()))/factor));
this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setAcceptHoverEvents(true);
this->setPath(ToolPath());
ToolCreation(typeCreation);
}
//---------------------------------------------------------------------------------------------------------------------
VToolCubicBezier::~VToolCubicBezier()
{
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::setDialog()
{
SCASSERT(dialog != nullptr);
auto dialogTool = qobject_cast<DialogCubicBezier*>(dialog);
SCASSERT(dialogTool != nullptr);
const auto spl = VAbstractTool::data.GeometricObject<VCubicBezier>(id);
dialogTool->SetSpline(*spl);
dialogTool->SetColor(lineColor);
}
//---------------------------------------------------------------------------------------------------------------------
VToolCubicBezier *VToolCubicBezier::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
VContainer *data)
{
SCASSERT(dialog != nullptr);
auto dialogTool = qobject_cast<DialogCubicBezier*>(dialog);
SCASSERT(dialogTool != nullptr);
auto spl = Create(0, new VCubicBezier(dialogTool->GetSpline()), dialogTool->GetColor(), scene, doc, data,
Document::FullParse, Source::FromGui);
if (spl != nullptr)
{
spl->dialog=dialogTool;
}
return spl;
}
//---------------------------------------------------------------------------------------------------------------------
VToolCubicBezier *VToolCubicBezier::Create(const quint32 _id, VCubicBezier *spline, const QString &color,
VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data,
const Document &parse, const Source &typeCreation)
{
quint32 id = _id;
if (typeCreation == Source::FromGui)
{
id = data->AddGObject(spline);
data->AddCurve<VCubicBezier>(id);
}
else
{
data->UpdateGObject(id, spline);
data->AddCurve<VCubicBezier>(id);
if (parse != Document::FullParse)
{
doc->UpdateToolData(id, data);
}
}
VDrawTool::AddRecord(id, Tool::CubicBezier, doc);
if (parse == Document::FullParse)
{
auto _spl = new VToolCubicBezier(doc, data, id, color, typeCreation);
scene->addItem(_spl);
connect(_spl, &VToolCubicBezier::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
connect(scene, &VMainGraphicsScene::NewFactor, _spl, &VToolCubicBezier::SetFactor);
connect(scene, &VMainGraphicsScene::DisableItem, _spl, &VToolCubicBezier::Disable);
doc->AddTool(id, _spl);
doc->IncrementReferens(spline->GetP1().getIdTool());
doc->IncrementReferens(spline->GetP1().getIdTool());
doc->IncrementReferens(spline->GetP1().getIdTool());
doc->IncrementReferens(spline->GetP4().getIdTool());
return _spl;
}
return nullptr;
}
//---------------------------------------------------------------------------------------------------------------------
VCubicBezier VToolCubicBezier::getSpline() const
{
auto spline = VAbstractTool::data.GeometricObject<VCubicBezier>(id);
return *spline.data();
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::setSpline(const VCubicBezier &spl)
{
QSharedPointer<VGObject> obj = VAbstractTool::data.GetGObject(id);
QSharedPointer<VCubicBezier> spline = qSharedPointerDynamicCast<VCubicBezier>(obj);
*spline.data() = spl;
SaveOption(obj);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::ShowVisualization(bool show)
{
ShowToolVisualization<VisToolCubicBezier>(show);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{
try
{
ContextMenu<DialogCubicBezier>(this, event);
}
catch(const VExceptionToolWasDeleted &e)
{
Q_UNUSED(e);
return;//Leave this method immediately!!!
}
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::RemoveReferens()
{
const auto spl = VAbstractTool::data.GeometricObject<VCubicBezier>(id);
doc->DecrementReferens(spl->GetP1().getIdTool());
doc->DecrementReferens(spl->GetP2().getIdTool());
doc->DecrementReferens(spl->GetP3().getIdTool());
doc->DecrementReferens(spl->GetP4().getIdTool());
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::SaveDialog(QDomElement &domElement)
{
SCASSERT(dialog != nullptr);
auto dialogTool = qobject_cast<DialogCubicBezier*>(dialog);
SCASSERT(dialogTool != nullptr);
const VCubicBezier spl = dialogTool->GetSpline();
SetSplineAttributes(domElement, spl);
doc->SetAttribute(domElement, AttrColor, dialogTool->GetColor());
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj)
{
VAbstractSpline::SaveOptions(tag, obj);
auto spl = qSharedPointerDynamicCast<VCubicBezier>(obj);
SCASSERT(spl.isNull() == false);
SetSplineAttributes(tag, *spl);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::SetVisualization()
{
if (vis != nullptr)
{
auto visual = qobject_cast<VisToolCubicBezier *>(vis);
SCASSERT(visual != nullptr);
const QSharedPointer<VCubicBezier> spl = VAbstractTool::data.GeometricObject<VCubicBezier>(id);
visual->setObject1Id(spl->GetP1().id());
visual->setObject2Id(spl->GetP2().id());
visual->setObject3Id(spl->GetP3().id());
visual->setObject4Id(spl->GetP4().id());
visual->SetMode(Mode::Show);
visual->RefreshGeometry();
}
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::RefreshGeometry()
{
this->setPen(QPen(CorrectColor(lineColor),
qApp->toPixel(WidthHairLine(*VAbstractTool::data.GetPatternUnit()))/factor));
if (isHovered || detailsMode)
{
this->setPath(ToolPath(PathDirection::Show));
}
else
{
this->setPath(ToolPath());
}
SetVisualization();
}
//---------------------------------------------------------------------------------------------------------------------
void VToolCubicBezier::SetSplineAttributes(QDomElement &domElement, const VCubicBezier &spl)
{
SCASSERT(doc != nullptr);
doc->SetAttribute(domElement, AttrType, ToolType);
doc->SetAttribute(domElement, AttrPoint1, spl.GetP1().id());
doc->SetAttribute(domElement, AttrPoint2, spl.GetP2().id());
doc->SetAttribute(domElement, AttrPoint3, spl.GetP3().id());
doc->SetAttribute(domElement, AttrPoint4, spl.GetP4().id());
if (spl.GetDuplicate() > 0)
{
doc->SetAttribute(domElement, AttrDuplicate, spl.GetDuplicate());
}
else
{
if (domElement.hasAttribute(AttrDuplicate))
{
domElement.removeAttribute(AttrDuplicate);
}
}
}

View file

@ -0,0 +1,70 @@
/************************************************************************
**
** @file vtoolcubicbezier.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 10 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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/>.
**
*************************************************************************/
#ifndef VTOOLCUBICBEZIER_H
#define VTOOLCUBICBEZIER_H
#include "vabstractspline.h"
class VCubicBezier;
class VToolCubicBezier : public VAbstractSpline
{
Q_OBJECT
public:
VToolCubicBezier(VAbstractPattern *doc, VContainer *data, quint32 id, const QString &color,
const Source &typeCreation, QGraphicsItem * parent = nullptr);
virtual ~VToolCubicBezier();
virtual void setDialog() Q_DECL_OVERRIDE;
static VToolCubicBezier *Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstractPattern *doc,
VContainer *data);
static VToolCubicBezier *Create(const quint32 _id, VCubicBezier *spline, const QString &color,
VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data,
const Document &parse, const Source &typeCreation);
static const QString ToolType;
virtual int type() const Q_DECL_OVERRIDE {return Type;}
enum { Type = UserType + static_cast<int>(Tool::CubicBezier)};
VCubicBezier getSpline()const;
void setSpline(const VCubicBezier &spl);
virtual void ShowVisualization(bool show) Q_DECL_OVERRIDE;
protected:
virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ) Q_DECL_OVERRIDE;
virtual void RemoveReferens() Q_DECL_OVERRIDE;
virtual void SaveDialog(QDomElement &domElement) Q_DECL_OVERRIDE;
virtual void SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj) Q_DECL_OVERRIDE;
virtual void SetVisualization() Q_DECL_OVERRIDE;
private:
Q_DISABLE_COPY(VToolCubicBezier)
void RefreshGeometry ();
void SetSplineAttributes(QDomElement &domElement, const VCubicBezier &spl);
};
#endif // VTOOLCUBICBEZIER_H

View file

@ -187,8 +187,8 @@ VToolSpline* VToolSpline::Create(const quint32 _id, VSpline *spline, const QStri
connect(scene, &VMainGraphicsScene::EnableToolMove, _spl, &VToolSpline::EnableToolMove);
connect(scene, &VMainGraphicsScene::CurveDetailsMode, _spl, &VToolSpline::DetailsMode);
doc->AddTool(id, _spl);
doc->IncrementReferens(spline->GetP1().id());
doc->IncrementReferens(spline->GetP4().id());
doc->IncrementReferens(spline->GetP1().getIdTool());
doc->IncrementReferens(spline->GetP4().getIdTool());
return _spl;
}
return nullptr;

View file

@ -120,7 +120,7 @@ VToolCutSpline* VToolCutSpline::Create(const quint32 _id, const QString &pointNa
VMainGraphicsScene *scene, VAbstractPattern *doc, VContainer *data,
const Document &parse, const Source &typeCreation)
{
const QSharedPointer<VSpline> spl = data->GeometricObject<VSpline>(splineId);
const auto spl = data->GeometricObject<VAbstractCubicBezier>(splineId);
const qreal result = CheckFormula(_id, formula, data);

View file

@ -47,7 +47,8 @@ HEADERS += \
$$PWD/drawTools/toolpoint/vabstractpoint.h \
$$PWD/drawTools/toolpoint/tooldoublepoint/vtooldoublepoint.h \
$$PWD/drawTools/toolpoint/tooldoublepoint/vtooltruedarts.h \
$$PWD/drawTools/toolpoint/toolsinglepoint/vtoolpointofintersectioncurves.h
$$PWD/drawTools/toolpoint/toolsinglepoint/vtoolpointofintersectioncurves.h \
$$PWD/drawTools/toolcurve/vtoolcubicbezier.h
SOURCES += \
$$PWD/vtooldetail.cpp \
@ -92,4 +93,5 @@ SOURCES += \
$$PWD/drawTools/toolpoint/vabstractpoint.cpp \
$$PWD/drawTools/toolpoint/tooldoublepoint/vtooldoublepoint.cpp \
$$PWD/drawTools/toolpoint/tooldoublepoint/vtooltruedarts.cpp \
$$PWD/drawTools/toolpoint/toolsinglepoint/vtoolpointofintersectioncurves.cpp
$$PWD/drawTools/toolpoint/toolsinglepoint/vtoolpointofintersectioncurves.cpp \
$$PWD/drawTools/toolcurve/vtoolcubicbezier.cpp

View file

@ -29,6 +29,7 @@
#include "vtooldetail.h"
#include "nodeDetails/nodedetails.h"
#include "../vgeometry/varc.h"
#include "../vgeometry/vcubicbezier.h"
#include "../vgeometry/vsplinepath.h"
#include "../vwidgets/vmaingraphicsscene.h"
#include "../vwidgets/vmaingraphicsview.h"
@ -178,7 +179,15 @@ void VToolDetail::Create(DialogTool *dialog, VMainGraphicsScene *scene, VAbstrac
break;
case (Tool::NodeSpline):
{
id = CreateNode<VSpline>(data, nodeD.getId());
const auto obj = data->GetGObject(nodeD.getId());
if (obj->getType() == GOType::Spline)
{
id = CreateNode<VSpline>(data, nodeD.getId());
}
else
{
id = CreateNode<VCubicBezier>(data, nodeD.getId());
}
VNodeSpline::Create(doc, data, id, nodeD.getId(), Document::FullParse, Source::FromGui);
}
break;

View file

@ -0,0 +1,122 @@
/************************************************************************
**
** @file vistoolcubicbezier.cpp
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 10 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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 "vistoolcubicbezier.h"
#include "../vgeometry/vcubicbezier.h"
//---------------------------------------------------------------------------------------------------------------------
VisToolCubicBezier::VisToolCubicBezier(const VContainer *data, QGraphicsItem *parent)
: VisPath(data, parent),
object2Id(NULL_ID),
object3Id(NULL_ID),
object4Id(NULL_ID),
point1(nullptr),
point2(nullptr),
point3(nullptr),
point4(nullptr),
helpLine(nullptr)
{
point1 = InitPoint(supportColor, this);
point2 = InitPoint(supportColor, this); //-V656
point3 = InitPoint(supportColor, this); //-V656
point4 = InitPoint(supportColor, this); //-V656
helpLine = InitItem<QGraphicsLineItem>(mainColor, this);
}
//---------------------------------------------------------------------------------------------------------------------
VisToolCubicBezier::~VisToolCubicBezier()
{
}
//---------------------------------------------------------------------------------------------------------------------
void VisToolCubicBezier::RefreshGeometry()
{
if (object1Id > NULL_ID)
{
const auto first = Visualization::data->GeometricObject<VPointF>(object1Id);
DrawPoint(point1, first->toQPointF(), supportColor);
if (object2Id <= NULL_ID)
{
const QLineF line = QLineF(first->toQPointF(), Visualization::scenePos);
DrawLine(helpLine, line, mainColor, lineStyle);
}
else
{
helpLine->setVisible(false);
const auto second = Visualization::data->GeometricObject<VPointF>(object2Id);
DrawPoint(point2, second->toQPointF(), supportColor);
if (object3Id <= NULL_ID)
{
VCubicBezier spline(*first, *second, VPointF(Visualization::scenePos),
VPointF(Visualization::scenePos));
DrawPath(this, spline.GetPath(PathDirection::Hide), mainColor, Qt::SolidLine, Qt::RoundCap);
}
else
{
const auto third = Visualization::data->GeometricObject<VPointF>(object3Id);
DrawPoint(point3, third->toQPointF(), supportColor);
if (object4Id <= NULL_ID)
{
VCubicBezier spline(*first, *second, *third, VPointF(Visualization::scenePos));
DrawPath(this, spline.GetPath(PathDirection::Hide), mainColor, Qt::SolidLine, Qt::RoundCap);
}
else
{
const auto fourth = Visualization::data->GeometricObject<VPointF>(object4Id);
DrawPoint(point4, fourth->toQPointF(), supportColor);
VCubicBezier spline(*first, *second, *third, *fourth);
DrawPath(this, spline.GetPath(PathDirection::Show), mainColor, Qt::SolidLine, Qt::RoundCap);
}
}
}
}
}
//---------------------------------------------------------------------------------------------------------------------
void VisToolCubicBezier::setObject2Id(const quint32 &value)
{
object2Id = value;
}
//---------------------------------------------------------------------------------------------------------------------
void VisToolCubicBezier::setObject3Id(const quint32 &value)
{
object3Id = value;
}
//---------------------------------------------------------------------------------------------------------------------
void VisToolCubicBezier::setObject4Id(const quint32 &value)
{
object4Id = value;
}

View file

@ -0,0 +1,62 @@
/************************************************************************
**
** @file vistoolcubicbezier.h
** @author Roman Telezhynskyi <dismine(at)gmail.com>
** @date 10 3, 2016
**
** @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) 2016 Valentina project
** <https://bitbucket.org/dismine/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/>.
**
*************************************************************************/
#ifndef VISTOOLCUBICBEZIER_H
#define VISTOOLCUBICBEZIER_H
#include "vispath.h"
class VisToolCubicBezier : public VisPath
{
Q_OBJECT
public:
explicit VisToolCubicBezier(const VContainer *data, QGraphicsItem *parent = nullptr);
virtual ~VisToolCubicBezier();
virtual void RefreshGeometry() Q_DECL_OVERRIDE;
void setObject2Id(const quint32 &value);
void setObject3Id(const quint32 &value);
void setObject4Id(const quint32 &value);
virtual int type() const Q_DECL_OVERRIDE {return Type;}
enum { Type = UserType + static_cast<int>(Vis::ToolCubicBezier)};
protected:
Q_DISABLE_COPY(VisToolCubicBezier)
quint32 object2Id;
quint32 object3Id;
quint32 object4Id;
QGraphicsEllipseItem *point1;
QGraphicsEllipseItem *point2;
QGraphicsEllipseItem *point3;
QGraphicsEllipseItem *point4;
QGraphicsLineItem *helpLine;
};
#endif // VISTOOLCUBICBEZIER_H

View file

@ -53,14 +53,20 @@ void VisToolCutSpline::RefreshGeometry()
{
if (object1Id > NULL_ID)
{
const QSharedPointer<VSpline> spl = Visualization::data->GeometricObject<VSpline>(object1Id);
const auto spl = Visualization::data->GeometricObject<VAbstractCubicBezier>(object1Id);
DrawPath(this, spl->GetPath(PathDirection::Show), supportColor, Qt::SolidLine, Qt::RoundCap);
if (qFuzzyCompare(1 + length, 1 + 0) == false)
{
VSpline sp1;
VSpline sp2;
QPointF p = spl->CutSpline(length, sp1, sp2);
QPointF spl1p2;
QPointF spl1p3;
QPointF spl2p2;
QPointF spl2p3;
const QPointF p = spl->CutSpline (length, spl1p2, spl1p3, spl2p2, spl2p3 );
const VSpline sp1 = VSpline(spl->GetP1(), spl1p2, spl1p3, p);
const VSpline sp2 = VSpline(p, spl2p2, spl2p3, spl->GetP4());
DrawPoint(point, p, mainColor);
DrawPath(spl1, sp1.GetPath(PathDirection::Show), Qt::darkGreen, Qt::SolidLine, Qt::RoundCap);

View file

@ -30,7 +30,8 @@ HEADERS += \
$$PWD/vistoolpointfromarcandtangent.h \
$$PWD/vistoolarcwithlength.h \
$$PWD/vistooltruedarts.h \
$$PWD/vistoolpointofintersectioncurves.h
$$PWD/vistoolpointofintersectioncurves.h \
$$PWD/vistoolcubicbezier.h
SOURCES += \
$$PWD/visline.cpp \
@ -61,4 +62,5 @@ SOURCES += \
$$PWD/vistoolpointfromarcandtangent.cpp \
$$PWD/vistoolarcwithlength.cpp \
$$PWD/vistooltruedarts.cpp \
$$PWD/vistoolpointofintersectioncurves.cpp
$$PWD/vistoolpointofintersectioncurves.cpp \
$$PWD/vistoolcubicbezier.cpp