Fixed issue #215. Drag a curve to edit it.

--HG--
branch : develop
This commit is contained in:
Roman Telezhynskyi 2015-02-13 11:27:21 +02:00
commit d8371aa04e
18 changed files with 450 additions and 17 deletions

View File

@ -744,3 +744,134 @@ void VSpline::SetKcurve(qreal factor)
d->kCurve = factor; d->kCurve = factor;
} }
} }
//---------------------------------------------------------------------------------------------------------------------
int VSpline::Sign(long double ld) const
{
if(qAbs(ld)<0.00000000001)
{
return 0;
}
return (ld>0) ? 1 : -1;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief Cubic Cubic equation solution. Real coefficients case.
*
* This method use method Vieta-Cardano for eval cubic equations.
* Cubic equation write in form x3+a*x2+b*x+c=0.
*
* Output:
* 3 real roots -> then x is filled with them;
* 1 real + 2 complex -> x[0] is real, x[1] is real part of complex roots, x[2] - non-negative imaginary part.
*
* @param x solution array (size 3).
* @param a coefficient
* @param b coefficient
* @param c coefficient
* @return 3 - 3 real roots;
* 1 - 1 real root + 2 complex;
* 2 - 1 real root + complex roots imaginary part is zero (i.e. 2 real roots).
*/
qint32 VSpline::Cubic(QVector<qreal> &x, qreal a, qreal b, qreal c) const
{
//To find cubic equation roots in the case of real coefficients, calculated at the beginning
const qreal q = (pow(a, 2) - 3*b)/9.;
const qreal r = (2*pow(a, 3) - 9*a*b + 27.*c)/54.;
if (pow(r, 2) < pow(q, 3))
{ // equation has three real roots, use formula Vieta
const qreal t = acos(r/sqrt(pow(q, 3)))/3.;
x.insert(0, -2.*sqrt(q)*cos(t)-a/3);
x.insert(1, -2.*sqrt(q)*cos(t + (2*M_2PI/3.)) - a/3.);
x.insert(2, -2.*sqrt(q)*cos(t - (2*M_2PI/3.)) - a/3.);
return(3);
}
else
{ // 1 real root + 2 complex
//Formula Cardano
const qreal aa = -Sign(r)*pow(fabs(r)+sqrt(pow(r, 2)-pow(q, 3)), 1./3.);
const qreal bb = Sign(aa) == 0 ? 0 : q/aa;
x.insert(0, aa+bb-a/3.); // Real root
x.insert(1, (-0.5)*(aa+bb)-a/3.); //Complex root
x.insert(2, (sqrt(3.)*0.5)*fabs(aa-bb)); // Complex root
if (qFuzzyCompare(x.at(2) + 1, 0. + 1))
{
return(2);
}
return(1);
}
}
//---------------------------------------------------------------------------------------------------------------------
QVector<qreal> VSpline::CalcT (qreal curveCoord1, qreal curveCoord2, qreal curveCoord3,
qreal curveCoord4, qreal pointCoord) const
{
const qreal a = -curveCoord1 + 3*curveCoord2 - 3*curveCoord3 + curveCoord4;
const qreal b = 3*curveCoord1 - 6*curveCoord2 + 3*curveCoord3;
const qreal c = -3*curveCoord1 + 3*curveCoord2;
const qreal d = -pointCoord + curveCoord1;
QVector<qreal> t = QVector<qreal>(3, -1);
Cubic(t, b/a, c/a, d/a);
QVector<qreal> retT;
for (int i=0; i < t.size(); ++i)
{
if ( t.at(i) >= 0 && t.at(i) <= 1 )
{
retT.append(t.at(i));
}
}
return retT;
}
//---------------------------------------------------------------------------------------------------------------------
/**
* @brief VSpline::ParamT calculate t coeffient that reprezent point on curve.
*
* Each point that belongs to Cubic Bézier curve can be shown by coefficient in interval [0; 1].
*
* @param pBt point on curve
* @return t coeffient that reprezent this point on curve. Return -1 if point doesn't belongs to curve.
*/
qreal VSpline::ParamT (const QPointF &pBt) const
{
QVector<qreal> ts;
// Calculate t coefficient for each axis
ts += CalcT (GetP1().toQPointF().x(), d->p2.x(), d->p3.x(), GetP4().toQPointF().x(), pBt.x());
ts += CalcT (GetP1().toQPointF().y(), d->p2.y(), d->p3.y(), GetP4().toQPointF().y(), pBt.y());
if(ts.isEmpty())
{
return -1; // We don't have candidates
}
qreal tx = -1;
qreal eps = 3; // Error calculation
// In morst case we will have 6 result in interval [0; 1].
// Here we try find closest to our point.
for (int i=0; i< ts.size(); ++i)
{
const qreal t = ts.at(i);
const QPointF p0 = GetP1().toQPointF();
const QPointF p1 = d->p2;
const QPointF p2 = d->p3;
const QPointF p3 = GetP4().toQPointF();
//The explicit form of the Cubic Bézier curve
const qreal pointX = pow(1-t, 3)*p0.x() + 3*pow(1-t, 2)*t*p1.x() + 3*(1-t)*pow(t, 2)*p2.x() + pow(t, 3)*p3.x();
const qreal pointY = pow(1-t, 3)*p0.y() + 3*pow(1-t, 2)*t*p1.y() + 3*(1-t)*pow(t, 2)*p2.y() + pow(t, 3)*p3.y();
const QLineF line(pBt, QPointF(pointX, pointY));
if (line.length() <= eps)
{
tx = t;
eps = line.length(); //Next point should be even closest
}
}
return tx;
}

View File

@ -71,6 +71,7 @@ public:
// cppcheck-suppress unusedFunction // cppcheck-suppress unusedFunction
static QVector<QPointF> SplinePoints(const QPointF &p1, const QPointF &p4, qreal angle1, qreal angle2, qreal kAsm1, static QVector<QPointF> SplinePoints(const QPointF &p1, const QPointF &p4, qreal angle1, qreal angle2, qreal kAsm1,
qreal kAsm2, qreal kCurve); qreal kAsm2, qreal kCurve);
qreal ParamT(const QPointF &pBt) const;
protected: protected:
static QVector<QPointF> GetPoints (const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4 ); static QVector<QPointF> GetPoints (const QPointF &p1, const QPointF &p2, const QPointF &p3, const QPointF &p4 );
private: private:
@ -80,6 +81,10 @@ private:
qint16 level, QVector<qreal> &px, QVector<qreal> &py); qint16 level, QVector<qreal> &px, QVector<qreal> &py);
static qreal CalcSqDistance ( qreal x1, qreal y1, qreal x2, qreal y2); static qreal CalcSqDistance ( qreal x1, qreal y1, qreal x2, qreal y2);
void CreateName(); void CreateName();
QVector<qreal> CalcT(qreal curveCoord1, qreal curveCoord2, qreal curveCoord3, qreal curveCoord4,
qreal pointCoord) const;
qint32 Cubic(QVector<qreal> &x, qreal a, qreal b, qreal c) const;
int Sign(long double ld) const;
}; };
#endif // VSPLINE_H #endif // VSPLINE_H

View File

@ -236,6 +236,30 @@ void VSplinePath::setMaxCountPoints(const qint32 &value)
d->maxCountPoints = value; d->maxCountPoints = value;
} }
//---------------------------------------------------------------------------------------------------------------------
int VSplinePath::Segment(const QPointF &p) const
{
int index = -1;
for (qint32 i = 1; i <= Count(); ++i)
{
VSpline spl = VSpline(d->path.at(i-1).P(), d->path.at(i).P(), d->path.at(i-1).Angle2(), d->path.at(i).Angle1(),
d->path.at(i-1).KAsm2(), d->path.at(i).KAsm1(), d->kCurve);
const qreal t = spl.ParamT(p);
if (qFloor(t) == -1)
{
continue;
}
else
{
index = i;
break;
}
}
return index;
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
qint32 VSplinePath::CountPoint() const qint32 VSplinePath::CountPoint() const
{ {

View File

@ -185,6 +185,8 @@ public:
* @param value max count. * @param value max count.
*/ */
void setMaxCountPoints(const qint32 &value); void setMaxCountPoints(const qint32 &value);
int Segment(const QPointF &p) const;
private: private:
QSharedDataPointer<VSplinePathData> d; QSharedDataPointer<VSplinePathData> d;
}; };

View File

@ -300,6 +300,7 @@ void MainWindow::SetToolButton(bool checked, Tool t, const QString &cursor, cons
if (checked) if (checked)
{ {
CancelTool(); CancelTool();
emit EnableItemMove(true);
tool = t; tool = t;
QPixmap pixmap(cursor); QPixmap pixmap(cursor);
QCursor cur(pixmap, 2, 3); QCursor cur(pixmap, 2, 3);
@ -340,6 +341,7 @@ void MainWindow::SetToolButtonWithApply(bool checked, Tool t, const QString &cur
if (checked) if (checked)
{ {
CancelTool(); CancelTool();
emit EnableItemMove(false);
tool = t; tool = t;
QPixmap pixmap(cursor); QPixmap pixmap(cursor);
QCursor cur(pixmap, 2, 3); QCursor cur(pixmap, 2, 3);
@ -1050,7 +1052,6 @@ void MainWindow::CancelTool()
ui->actionArrowTool->setChecked(false); ui->actionArrowTool->setChecked(false);
helpLabel->setText(""); helpLabel->setText("");
ui->actionStopTool->setEnabled(true); ui->actionStopTool->setEnabled(true);
emit EnableItemMove(false);
return; return;
case Tool::SinglePoint: case Tool::SinglePoint:
Q_UNREACHABLE(); Q_UNREACHABLE();
@ -1130,7 +1131,6 @@ void MainWindow::CancelTool()
} }
currentScene->setFocus(Qt::OtherFocusReason); currentScene->setFocus(Qt::OtherFocusReason);
currentScene->clearSelection(); currentScene->clearSelection();
emit EnableItemMove(true);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
@ -1998,13 +1998,13 @@ bool MainWindow::SavePattern(const QString &fileName, QString &error)
setCurrentFile(fileName); setCurrentFile(fileName);
helpLabel->setText(tr("File saved")); helpLabel->setText(tr("File saved"));
qCDebug(vMainWindow)<<"File"<<fileName<<"saved."; qCDebug(vMainWindow)<<"File"<<fileName<<"saved.";
PatternWasModified(result);
} }
} }
else else
{ {
qCDebug(vMainWindow)<<"Could not save file"<<fileName<<"."<<error<<"."; qCDebug(vMainWindow)<<"Could not save file"<<fileName<<"."<<error<<".";
} }
PatternWasModified(result);
return result; return result;
} }

View File

@ -37,6 +37,9 @@ const QString nameRegExp = QStringLiteral("^([^0-9-*/^+=\\s\\(\\)%:;!.,`'\"]){1,
// furthermore blows up the binary sizes. // furthermore blows up the binary sizes.
const QString degreeSymbol = QStringLiteral("°"); const QString degreeSymbol = QStringLiteral("°");
const QString cursorArrowOpenHand = QStringLiteral("://cursor/cursor-arrow-openhand.png");
const QString cursorArrowCloseHand = QStringLiteral("://cursor/cursor-arrow-closehand.png");
// Keep synchronize all names with initialization in VApllication class!!!!! // Keep synchronize all names with initialization in VApllication class!!!!!
//measurements //measurements
//head and neck //head and neck

View File

@ -50,6 +50,9 @@ class QStringList;
extern const QString nameRegExp; extern const QString nameRegExp;
extern const QString degreeSymbol; extern const QString degreeSymbol;
extern const QString cursorArrowOpenHand;
extern const QString cursorArrowCloseHand;
enum class SceneObject : char { Point, Line, Spline, Arc, SplinePath, Detail, Unknown }; enum class SceneObject : char { Point, Line, Spline, Arc, SplinePath, Detail, Unknown };
enum class Tool : unsigned char enum class Tool : unsigned char
{ {

View File

@ -47,11 +47,14 @@ VToolCut::VToolCut(VPattern *doc, VContainer *data, const quint32 &id, const QSt
firstCurve->setParentItem(this); firstCurve->setParentItem(this);
connect(firstCurve, &VSimpleCurve::Choosed, this, &VToolCut::CurveChoosed); connect(firstCurve, &VSimpleCurve::Choosed, this, &VToolCut::CurveChoosed);
connect(firstCurve, &VSimpleCurve::HoverPath, this, &VToolCut::HoverPath); connect(firstCurve, &VSimpleCurve::HoverPath, this, &VToolCut::HoverPath);
// TODO: Now we only hide simple curves, but in future need totally delete them all.
firstCurve->setVisible(false);
secondCurve = new VSimpleCurve(curve2id, QColor(lineColor), SimpleCurvePoint::FirstPoint, &factor); secondCurve = new VSimpleCurve(curve2id, QColor(lineColor), SimpleCurvePoint::FirstPoint, &factor);
secondCurve->setParentItem(this); secondCurve->setParentItem(this);
connect(secondCurve, &VSimpleCurve::Choosed, this, &VToolCut::CurveChoosed); connect(secondCurve, &VSimpleCurve::Choosed, this, &VToolCut::CurveChoosed);
connect(secondCurve, &VSimpleCurve::HoverPath, this, &VToolCut::HoverPath); connect(secondCurve, &VSimpleCurve::HoverPath, this, &VToolCut::HoverPath);
secondCurve->setVisible(false);
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------

View File

@ -33,6 +33,7 @@
#include "../../undocommands/addpatternpiece.h" #include "../../undocommands/addpatternpiece.h"
#include "../../undocommands/deletepatternpiece.h" #include "../../undocommands/deletepatternpiece.h"
#include "../../geometry/vpointf.h" #include "../../geometry/vpointf.h"
#include "../../options.h"
#include <QMessageBox> #include <QMessageBox>
@ -207,7 +208,7 @@ void VToolSinglePoint::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
if (flags() & QGraphicsItem::ItemIsMovable) if (flags() & QGraphicsItem::ItemIsMovable)
{ {
VApplication::setOverrideCursor(QStringLiteral("://cursor/cursor-arrow-openhand.png"), 1, 1); VApplication::setOverrideCursor(cursorArrowOpenHand, 1, 1);
} }
} }
@ -219,7 +220,7 @@ void VToolSinglePoint::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
if (flags() & QGraphicsItem::ItemIsMovable) if (flags() & QGraphicsItem::ItemIsMovable)
{ {
//Disable cursor-arrow-openhand //Disable cursor-arrow-openhand
VApplication::restoreOverrideCursor(QStringLiteral("://cursor/cursor-arrow-openhand.png")); VApplication::restoreOverrideCursor(cursorArrowOpenHand);
} }
} }
@ -230,7 +231,7 @@ void VToolSinglePoint::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{ {
VApplication::setOverrideCursor(QStringLiteral("://cursor/cursor-arrow-closehand.png"), 1, 1); VApplication::setOverrideCursor(cursorArrowCloseHand, 1, 1);
} }
} }
VToolPoint::mousePressEvent(event); VToolPoint::mousePressEvent(event);
@ -244,7 +245,7 @@ void VToolSinglePoint::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{ {
//Disable cursor-arrow-closehand //Disable cursor-arrow-closehand
VApplication::restoreOverrideCursor(QStringLiteral("://cursor/cursor-arrow-closehand.png")); VApplication::restoreOverrideCursor(cursorArrowCloseHand);
} }
} }
VToolPoint::mouseReleaseEvent(event); VToolPoint::mouseReleaseEvent(event);

View File

@ -31,6 +31,8 @@
#include "../../dialogs/tools/dialogspline.h" #include "../../dialogs/tools/dialogspline.h"
#include "../../undocommands/movespline.h" #include "../../undocommands/movespline.h"
#include "../../visualization/vistoolspline.h" #include "../../visualization/vistoolspline.h"
#include "../../options.h"
#include <QtMath>
const QString VToolSpline::ToolType = QStringLiteral("simple"); const QString VToolSpline::ToolType = QStringLiteral("simple");
@ -45,7 +47,7 @@ const QString VToolSpline::ToolType = QStringLiteral("simple");
*/ */
VToolSpline::VToolSpline(VPattern *doc, VContainer *data, quint32 id, const QString color, const Source &typeCreation, VToolSpline::VToolSpline(VPattern *doc, VContainer *data, quint32 id, const QString color, const Source &typeCreation,
QGraphicsItem *parent) QGraphicsItem *parent)
:VAbstractSpline(doc, data, id, parent) :VAbstractSpline(doc, data, id, parent), oldPosition()
{ {
sceneType = SceneObject::Spline; sceneType = SceneObject::Spline;
lineColor = color; lineColor = color;
@ -53,6 +55,7 @@ VToolSpline::VToolSpline(VPattern *doc, VContainer *data, quint32 id, const QStr
this->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthHairLine())/factor)); this->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthHairLine())/factor));
this->setFlag(QGraphicsItem::ItemIsSelectable, true); this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true); this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setFlag(QGraphicsItem::ItemIsMovable, true);
this->setAcceptHoverEvents(true); this->setAcceptHoverEvents(true);
this->setPath(ToolPath()); this->setPath(ToolPath());
@ -190,6 +193,7 @@ VToolSpline* VToolSpline::Create(const quint32 _id, const quint32 &p1, const qui
connect(spl, &VToolSpline::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem); connect(spl, &VToolSpline::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
connect(scene, &VMainGraphicsScene::NewFactor, spl, &VToolSpline::SetFactor); connect(scene, &VMainGraphicsScene::NewFactor, spl, &VToolSpline::SetFactor);
connect(scene, &VMainGraphicsScene::DisableItem, spl, &VToolSpline::Disable); connect(scene, &VMainGraphicsScene::DisableItem, spl, &VToolSpline::Disable);
connect(scene, &VMainGraphicsScene::EnableToolMove, spl, &VToolSpline::EnableToolMove);
doc->AddTool(id, spl); doc->AddTool(id, spl);
doc->IncrementReferens(p1); doc->IncrementReferens(p1);
doc->IncrementReferens(p4); doc->IncrementReferens(p4);
@ -280,6 +284,12 @@ void VToolSpline::ControlPointChangePosition(const qint32 &indexSpline, const Sp
qApp->getUndoStack()->push(moveSpl); qApp->getUndoStack()->push(moveSpl);
} }
//---------------------------------------------------------------------------------------------------------------------
void VToolSpline::EnableToolMove(bool move)
{
this->setFlag(QGraphicsItem::ItemIsMovable, move);
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief contextMenuEvent handle context menu events. * @brief contextMenuEvent handle context menu events.
@ -355,6 +365,111 @@ void VToolSpline::SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj)
doc->SetAttribute(tag, AttrColor, lineColor); doc->SetAttribute(tag, AttrColor, lineColor);
} }
//---------------------------------------------------------------------------------------------------------------------
void VToolSpline::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (flags() & QGraphicsItem::ItemIsMovable)
{
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{
VApplication::setOverrideCursor(cursorArrowCloseHand, 1, 1);
oldPosition = event->scenePos();
event->accept();
}
}
VAbstractSpline::mousePressEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSpline::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (flags() & QGraphicsItem::ItemIsMovable)
{
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{
//Disable cursor-arrow-closehand
VApplication::restoreOverrideCursor(cursorArrowCloseHand);
}
}
VAbstractSpline::mouseReleaseEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSpline::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
// Don't need check if left mouse button was pressed. According to the Qt documentation "If you do receive this
// event, you can be certain that this item also received a mouse press event, and that this item is the current
// mouse grabber.".
// Magic Bezier Drag Equations follow!
// "weight" describes how the influence of the drag should be distributed
// among the handles; 0 = front handle only, 1 = back handle only.
const QSharedPointer<VSpline> spline = VAbstractTool::data.GeometricObject<VSpline>(id);
const qreal t = spline->ParamT(oldPosition);
if (qFloor(t) == -1)
{
return;
}
double weight;
if (t <= 1.0 / 6.0)
{
weight = 0;
}
else if (t <= 0.5)
{
weight = (pow((6 * t - 1) / 2.0, 3)) / 2;
}
else if (t <= 5.0 / 6.0)
{
weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5;
}
else
{
weight = 1;
}
const QPointF delta = event->scenePos() - oldPosition;
const QPointF offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta;
const QPointF offset1 = (weight/(3*t*t*(1-t))) * delta;
const QPointF p2 = spline->GetP2() + offset0;
const QPointF p3 = spline->GetP3() + offset1;
oldPosition = event->scenePos(); // Now mouse here
VSpline spl = VSpline(spline->GetP1(), p2, p3, spline->GetP4(), spline->GetKcurve());
MoveSpline *moveSpl = new MoveSpline(doc, spline.data(), spl, id, this->scene());
connect(moveSpl, &MoveSpline::NeedLiteParsing, doc, &VPattern::LiteParseTree);
qApp->getUndoStack()->push(moveSpl);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSpline::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
if (flags() & QGraphicsItem::ItemIsMovable)
{
VApplication::setOverrideCursor(cursorArrowOpenHand, 1, 1);
}
VAbstractSpline::hoverEnterEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSpline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
if (flags() & QGraphicsItem::ItemIsMovable)
{
//Disable cursor-arrow-openhand
VApplication::restoreOverrideCursor(cursorArrowOpenHand);
}
VAbstractSpline::hoverLeaveEvent(event);
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief RefreshGeometry refresh item on scene. * @brief RefreshGeometry refresh item on scene.

View File

@ -58,14 +58,21 @@ public:
public slots: public slots:
void ControlPointChangePosition (const qint32 &indexSpline, const SplinePointPosition &position, void ControlPointChangePosition (const qint32 &indexSpline, const SplinePointPosition &position,
const QPointF &pos); const QPointF &pos);
virtual void EnableToolMove(bool move);
protected: protected:
virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ); virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event );
virtual void RemoveReferens(); virtual void RemoveReferens();
virtual void SaveDialog(QDomElement &domElement); virtual void SaveDialog(QDomElement &domElement);
virtual void SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj); virtual void SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj);
virtual void mousePressEvent(QGraphicsSceneMouseEvent * event);
virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event );
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );
private: private:
Q_DISABLE_COPY(VToolSpline) Q_DISABLE_COPY(VToolSpline)
void RefreshGeometry (); void RefreshGeometry ();
QPointF oldPosition;
}; };
#endif // VTOOLSPLINE_H #endif // VTOOLSPLINE_H

View File

@ -44,7 +44,7 @@ const QString VToolSplinePath::ToolType = QStringLiteral("path");
*/ */
VToolSplinePath::VToolSplinePath(VPattern *doc, VContainer *data, quint32 id, const QString &color, VToolSplinePath::VToolSplinePath(VPattern *doc, VContainer *data, quint32 id, const QString &color,
const Source &typeCreation, QGraphicsItem *parent) const Source &typeCreation, QGraphicsItem *parent)
:VAbstractSpline(doc, data, id, parent) :VAbstractSpline(doc, data, id, parent), oldPosition()
{ {
sceneType = SceneObject::SplinePath; sceneType = SceneObject::SplinePath;
@ -52,6 +52,7 @@ VToolSplinePath::VToolSplinePath(VPattern *doc, VContainer *data, quint32 id, co
this->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthHairLine())/factor)); this->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthHairLine())/factor));
this->setFlag(QGraphicsItem::ItemIsSelectable, true); this->setFlag(QGraphicsItem::ItemIsSelectable, true);
this->setFlag(QGraphicsItem::ItemIsFocusable, true); this->setFlag(QGraphicsItem::ItemIsFocusable, true);
this->setFlag(QGraphicsItem::ItemIsMovable, true);
this->setAcceptHoverEvents(true); this->setAcceptHoverEvents(true);
const QSharedPointer<VSplinePath> splPath = data->GeometricObject<VSplinePath>(id); const QSharedPointer<VSplinePath> splPath = data->GeometricObject<VSplinePath>(id);
@ -167,6 +168,7 @@ VToolSplinePath* VToolSplinePath::Create(const quint32 _id, VSplinePath *path, c
connect(spl, &VToolSplinePath::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem); connect(spl, &VToolSplinePath::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem);
connect(scene, &VMainGraphicsScene::NewFactor, spl, &VToolSplinePath::SetFactor); connect(scene, &VMainGraphicsScene::NewFactor, spl, &VToolSplinePath::SetFactor);
connect(scene, &VMainGraphicsScene::DisableItem, spl, &VToolSplinePath::Disable); connect(scene, &VMainGraphicsScene::DisableItem, spl, &VToolSplinePath::Disable);
connect(scene, &VMainGraphicsScene::EnableToolMove, spl, &VToolSplinePath::EnableToolMove);
doc->AddTool(id, spl); doc->AddTool(id, spl);
return spl; return spl;
} }
@ -202,6 +204,12 @@ void VToolSplinePath::ControlPointChangePosition(const qint32 &indexSpline, cons
qApp->getUndoStack()->push(moveSplPath); qApp->getUndoStack()->push(moveSplPath);
} }
//---------------------------------------------------------------------------------------------------------------------
void VToolSplinePath::EnableToolMove(bool move)
{
this->setFlag(QGraphicsItem::ItemIsMovable, move);
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief UpdateControlPoints update position points control points in file. * @brief UpdateControlPoints update position points control points in file.
@ -414,6 +422,121 @@ void VToolSplinePath::SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &ob
} }
} }
//---------------------------------------------------------------------------------------------------------------------
void VToolSplinePath::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if (flags() & QGraphicsItem::ItemIsMovable)
{
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{
VApplication::setOverrideCursor(cursorArrowCloseHand, 1, 1);
oldPosition = event->scenePos();
event->accept();
}
}
VAbstractSpline::mousePressEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSplinePath::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (flags() & QGraphicsItem::ItemIsMovable)
{
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{
//Disable cursor-arrow-closehand
VApplication::restoreOverrideCursor(cursorArrowCloseHand);
}
}
VAbstractSpline::mouseReleaseEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSplinePath::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
// Don't need check if left mouse button was pressed. According to the Qt documentation "If you do receive this
// event, you can be certain that this item also received a mouse press event, and that this item is the current
// mouse grabber.".
VSplinePath oldSplPath = *VAbstractTool::data.GeometricObject<VSplinePath>(id);
VSplinePath newSplPath = oldSplPath;
int indexSpline = oldSplPath.Segment(oldPosition);
if (indexSpline == -1)
{
return;
}
VSpline spline = newSplPath.GetSpline(indexSpline);
const qreal t = spline.ParamT(oldPosition);
if (qFloor(t) == -1)
{
return;
}
// Magic Bezier Drag Equations follow!
// "weight" describes how the influence of the drag should be distributed
// among the handles; 0 = front handle only, 1 = back handle only.
double weight;
if (t <= 1.0 / 6.0)
{
weight = 0;
}
else if (t <= 0.5)
{
weight = (pow((6 * t - 1) / 2.0, 3)) / 2;
}
else if (t <= 5.0 / 6.0)
{
weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5;
}
else
{
weight = 1;
}
const QPointF delta = event->scenePos() - oldPosition;
const QPointF offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta;
const QPointF offset1 = (weight/(3*t*t*(1-t))) * delta;
const QPointF p2 = spline.GetP2() + offset0;
const QPointF p3 = spline.GetP3() + offset1;
oldPosition = event->scenePos(); // Now mouse here
const VSpline spl = VSpline(spline.GetP1(), p2, p3, spline.GetP4(), spline.GetKcurve());
UpdateControlPoints(spl, newSplPath, indexSpline);
MoveSplinePath *moveSplPath = new MoveSplinePath(doc, oldSplPath, newSplPath, id, this->scene());
connect(moveSplPath, &VUndoCommand::NeedLiteParsing, doc, &VPattern::LiteParseTree);
qApp->getUndoStack()->push(moveSplPath);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSplinePath::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
if (flags() & QGraphicsItem::ItemIsMovable)
{
VApplication::setOverrideCursor(cursorArrowOpenHand, 1, 1);
}
VAbstractSpline::hoverEnterEvent(event);
}
//---------------------------------------------------------------------------------------------------------------------
void VToolSplinePath::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
if (flags() & QGraphicsItem::ItemIsMovable)
{
//Disable cursor-arrow-openhand
VApplication::restoreOverrideCursor(cursorArrowOpenHand);
}
VAbstractSpline::hoverLeaveEvent(event);
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
/** /**
* @brief RefreshGeometry refresh item on scene. * @brief RefreshGeometry refresh item on scene.

View File

@ -73,13 +73,21 @@ public slots:
void ControlPointChangePosition(const qint32 &indexSpline, const SplinePointPosition &position, void ControlPointChangePosition(const qint32 &indexSpline, const SplinePointPosition &position,
const QPointF &pos); const QPointF &pos);
virtual void EnableToolMove(bool move);
protected: protected:
virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event ); virtual void contextMenuEvent ( QGraphicsSceneContextMenuEvent * event );
virtual void RefreshDataInFile(); virtual void RefreshDataInFile();
virtual void RemoveReferens(); virtual void RemoveReferens();
virtual void SaveDialog(QDomElement &domElement); virtual void SaveDialog(QDomElement &domElement);
virtual void SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj); virtual void SaveOptions(QDomElement &tag, QSharedPointer<VGObject> &obj);
virtual void mousePressEvent(QGraphicsSceneMouseEvent * event);
virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event );
virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );
private: private:
QPointF oldPosition;
void RefreshGeometry(); void RefreshGeometry();
static void AddPathPoint(VPattern *doc, QDomElement &domElement, const VSplinePoint &splPoint); static void AddPathPoint(VPattern *doc, QDomElement &domElement, const VSplinePoint &splPoint);
void UpdateControlPoints(const VSpline &spl, VSplinePath &splPath, const qint32 &indexSpline) const; void UpdateControlPoints(const VSpline &spl, VSplinePath &splPath, const qint32 &indexSpline) const;

View File

@ -90,7 +90,7 @@ void VControlPointSpline::paint(QPainter *painter, const QStyleOptionGraphicsIte
void VControlPointSpline::hoverEnterEvent(QGraphicsSceneHoverEvent *event) void VControlPointSpline::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{ {
this->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthMainLine()))); this->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthMainLine())));
VApplication::setOverrideCursor(QStringLiteral("://cursor/cursor-arrow-openhand.png"), 1, 1); VApplication::setOverrideCursor(cursorArrowOpenHand, 1, 1);
QGraphicsEllipseItem::hoverEnterEvent(event); QGraphicsEllipseItem::hoverEnterEvent(event);
} }
@ -99,7 +99,7 @@ void VControlPointSpline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{ {
this->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthHairLine()))); this->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthHairLine())));
//Disable cursor-arrow-openhand //Disable cursor-arrow-openhand
VApplication::restoreOverrideCursor(QStringLiteral("://cursor/cursor-arrow-openhand.png")); VApplication::restoreOverrideCursor(cursorArrowOpenHand);
QGraphicsEllipseItem::hoverLeaveEvent(event); QGraphicsEllipseItem::hoverLeaveEvent(event);
} }
@ -126,7 +126,7 @@ void VControlPointSpline::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{ {
VApplication::setOverrideCursor(QStringLiteral("://cursor/cursor-arrow-closehand.png"), 1, 1); VApplication::setOverrideCursor(cursorArrowCloseHand, 1, 1);
} }
QGraphicsEllipseItem::mousePressEvent(event); QGraphicsEllipseItem::mousePressEvent(event);
} }
@ -137,7 +137,7 @@ void VControlPointSpline::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{ {
//Disable cursor-arrow-closehand //Disable cursor-arrow-closehand
VApplication::restoreOverrideCursor(QStringLiteral("://cursor/cursor-arrow-closehand.png")); VApplication::restoreOverrideCursor(cursorArrowCloseHand);
} }
QGraphicsEllipseItem::mouseReleaseEvent(event); QGraphicsEllipseItem::mouseReleaseEvent(event);
} }

View File

@ -124,7 +124,7 @@ void VGraphicsSimpleTextItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{ {
this->setBrush(Qt::green); this->setBrush(Qt::green);
VApplication::setOverrideCursor(QStringLiteral("://cursor/cursor-arrow-openhand.png"), 1, 1); VApplication::setOverrideCursor(cursorArrowOpenHand, 1, 1);
QGraphicsSimpleTextItem::hoverEnterEvent(event); QGraphicsSimpleTextItem::hoverEnterEvent(event);
} }
@ -139,7 +139,7 @@ void VGraphicsSimpleTextItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
this->setBrush(Qt::black); this->setBrush(Qt::black);
//Disable cursor-arrow-openhand //Disable cursor-arrow-openhand
VApplication::restoreOverrideCursor(QStringLiteral("://cursor/cursor-arrow-openhand.png")); VApplication::restoreOverrideCursor(cursorArrowOpenHand);
QGraphicsSimpleTextItem::hoverLeaveEvent(event); QGraphicsSimpleTextItem::hoverLeaveEvent(event);
} }
@ -158,7 +158,7 @@ void VGraphicsSimpleTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{ {
VApplication::setOverrideCursor(QStringLiteral("://cursor/cursor-arrow-closehand.png"), 1, 1); VApplication::setOverrideCursor(cursorArrowCloseHand, 1, 1);
} }
QGraphicsSimpleTextItem::mousePressEvent(event); QGraphicsSimpleTextItem::mousePressEvent(event);
} }
@ -169,7 +169,7 @@ void VGraphicsSimpleTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick)
{ {
//Disable cursor-arrow-closehand //Disable cursor-arrow-closehand
VApplication::restoreOverrideCursor(QStringLiteral("://cursor/cursor-arrow-closehand.png")); VApplication::restoreOverrideCursor(cursorArrowCloseHand);
} }
QGraphicsSimpleTextItem::mouseReleaseEvent(event); QGraphicsSimpleTextItem::mouseReleaseEvent(event);
} }

View File

@ -144,6 +144,12 @@ void VSimpleCurve::SetCurrentColor(const QColor &value)
setPen(QPen(CorrectColor(currentColor), pen().widthF())); setPen(QPen(CorrectColor(currentColor), pen().widthF()));
} }
//---------------------------------------------------------------------------------------------------------------------
void VSimpleCurve::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
event->ignore();
}
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
QColor VSimpleCurve::CorrectColor(const QColor &color) const QColor VSimpleCurve::CorrectColor(const QColor &color) const
{ {

View File

@ -60,6 +60,7 @@ signals:
void Choosed(quint32 id); void Choosed(quint32 id);
void HoverPath(quint32 id, SimpleCurvePoint curvePosition, PathDirection direction); void HoverPath(quint32 id, SimpleCurvePoint curvePosition, PathDirection direction);
protected: protected:
virtual void mousePressEvent(QGraphicsSceneMouseEvent * event);
virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ); virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event );
virtual void hoverMoveEvent ( QGraphicsSceneHoverEvent * event ); virtual void hoverMoveEvent ( QGraphicsSceneHoverEvent * event );
virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event );

View File

@ -122,6 +122,7 @@
<xs:attribute name="arc" type="xs:unsignedInt"></xs:attribute> <xs:attribute name="arc" type="xs:unsignedInt"></xs:attribute>
<xs:attribute name="curve" type="xs:unsignedInt"></xs:attribute> <xs:attribute name="curve" type="xs:unsignedInt"></xs:attribute>
<xs:attribute name="lineColor" type="colors"></xs:attribute> <xs:attribute name="lineColor" type="colors"></xs:attribute>
<xs:attribute name="color" type="colors"></xs:attribute>
</xs:complexType> </xs:complexType>
</xs:element> </xs:element>
<xs:element name="line" minOccurs="0" maxOccurs="unbounded"> <xs:element name="line" minOccurs="0" maxOccurs="unbounded">