11#include <klocalizedstring.h>
14#include <QPainterPath>
15#include <QLinearGradient>
47 this->
xnorm = this->
x * (u - l) + l;
70 : prevStrokebegin(0,0)
82 , m_canvas(rhs.m_canvas)
93inline QPointF
B(qreal t,
const QPointF& P0,
const QPointF& P1,
const QPointF& P2,
const QPointF& P3)
95 const qreal tp = 1 - t;
96 const qreal tp2 = tp * tp;
97 const qreal t2 = t * t;
99 return ( tp2 * tp) * P0 +
100 (3 * tp2 * t ) * P1 +
105inline qreal
D(qreal t,
const QPointF& P0,
const QPointF& P1,
const QPointF& P2,
const QPointF& P3,
const QPointF&
p)
115 x_dist = a*P0.x() + b*P1.x() + c*P2.x() + d*P3.x() -
p.x(),
116 y_dist = a*P0.y() + b*P1.y() + c*P2.y() + d*P3.y() -
p.y();
118 return x_dist * x_dist + y_dist * y_dist;
134 const qreal ratio = 1 - 2/(1 + sqrt(5));
143 p[1].fval =
D(
p[1].xnorm, *handles[0], *handles[2], *handles[3], *handles[1], pt);
144 p[2].fval =
D(
p[2].xnorm, *handles[0], *handles[2], *handles[3], *handles[1], pt);
149 while ( qAbs(
p[2].xnorm -
p[1].xnorm) > tolerance && i < max_iter) {
151 if (
p[1].fval <
p[2].fval) {
154 p[1].
x =
p[0].x + (
p[2].x -
p[1].x);
158 p[1].fval =
D(
p[1].xnorm, *handles[0], *handles[2], *handles[3], *handles[1], pt);
163 p[2].
x =
p[1].x + (
p[3].x -
p[2].x);
167 p[2].fval =
D(
p[2].xnorm, *handles[0], *handles[2], *handles[3], *handles[1], pt);
172 return (
p[2].xnorm +
p[1].xnorm) / 2;
181 bool stayClose = (
m_d->prevStrokebegin == strokeBegin)?
true :
false;
186 Q_FOREACH(
int i, hindex) {
193 qreal delta = 1/10.0;
194 qreal lbound = qBound(0.0,1.0,
m_d->prev_t - delta);
195 qreal ubound = qBound(0.0,1.0,
m_d->prev_t + delta);
205 m_d->prevStrokebegin = strokeBegin;
212 return project(pt, strokeBegin);
218 strokeBegin = QPointF();
229 mousePos= canvas->
canvasWidget()->mapFromGlobal(QCursor::pos());
234 mousePos = QCursor::pos();
235 dbgFile<<
"canvas does not exist in spline, you may have passed arguments incorrectly:"<<canvas;
249 gc.setTransform(initialTransform);
254 path.cubicTo(pts[2], pts[3], pts[1]);
257 if (
isSnappingActive() && path.boundingRect().contains(initialTransform.inverted().map(mousePos)) && previewVisible==
true){
272 if (assistantVisible ==
false ||
handles().size() < 2 ){
284 gc.setTransform(initialTransform);
290 QPen bezierlinePen(assistantColor);
291 bezierlinePen.setStyle(Qt::DotLine);
292 bezierlinePen.setWidth(2);
297 QColor snappingColor = assistantColor;
298 snappingColor.setAlpha(snappingColor.alpha() * 0.2);
300 bezierlinePen.setColor(snappingColor);
302 bezierlinePen.setCosmetic(
true);
304 gc.setPen(bezierlinePen);
305 gc.drawLine(pts[0], pts[2]);
308 gc.drawLine(pts[1], pts[3]);
310 gc.setPen(QColor(0, 0, 0, 125));
319 path.cubicTo(pts[2], pts[3], pts[1]);
350 return i18nc(
"A type of drawing assistants",
"Spline");
qreal D(qreal t, const QPointF &P0, const QPointF &P1, const QPointF &P2, const QPointF &P3, const QPointF &p)
qreal goldenSearch(const QPointF &pt, const QList< KisPaintingAssistantHandleSP > handles, qreal low, qreal high, qreal tolerance, uint max_iter)
KisAbstractCanvasWidget * canvasWidget
KisPaintingAssistantsDecorationSP paintingAssistantsDecoration() const
QTransform documentToWidgetTransform() const
bool isSnappingActive() const
void drawPath(QPainter &painter, const QPainterPath &path, bool drawActive=true)
void drawPreview(QPainter &painter, const QPainterPath &path)
QColor effectiveAssistantColor() const
virtual void drawAssistant(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached, KisCanvas2 *canvas=0, bool assistantVisible=true, bool previewVisible=true)
const QList< KisPaintingAssistantHandleSP > & handles() const
bool isEditingAssistants()
QString id() const override
KisPaintingAssistant * createPaintingAssistant() const override
~SplineAssistantFactory() override
QString name() const override
KisPaintingAssistantSP clone(QMap< KisPaintingAssistantHandleSP, KisPaintingAssistantHandleSP > &handleMap) const override
void drawAssistant(QPainter &gc, const QRectF &updateRect, const KisCoordinatesConverter *converter, bool cached, KisCanvas2 *canvas, bool assistantVisible=true, bool previewVisible=true) override
const QScopedPointer< Private > m_d
KisCanvas2 * m_canvas
used for getting the decoration so the bezier handles aren't drawn while editing
QPointF project(const QPointF &pt, const QPointF &strokeBegin) const
void adjustLine(QPointF &point, QPointF &strokeBegin) override
void drawCache(QPainter &gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) override
performance layer where the graphics can be drawn from a cache instead of generated every render upda...
QPointF getDefaultEditorPosition() const override
bool isAssistantComplete() const override
QPointF adjustPosition(const QPointF &point, const QPointF &strokeBegin, const bool snapToAny, qreal moveThresholdPt) override
QSharedPointer< KisPaintingAssistant > KisPaintingAssistantSP
qreal nearestPoint(const QList< QPointF > controlPoints, const QPointF &point, qreal *resultDistance, QPointF *resultPoint)
GoldenSearchPoint(qreal xval)
void inv_norm(qreal l, qreal u)
QVector< GoldenSearchPoint > samples
GoldenSearchParams(qreal lbound, qreal ubound)