10#include <QElapsedTimer>
13#include <klocalizedstring.h>
125 return QPoint(qFloor(pos.x()), qFloor(pos.y()));
131 info.
setPos(QPointF(qreal(pixelPos.x()) + 0.5, qreal(pixelPos.y()) + 0.5));
222 distanceInfo = *buddyDistance;
259 const QPointF &pixelCoords,
376 QPointF tangent1, QPointF tangent2)
378 if (tangent1.isNull() || tangent2.isNull())
return;
380 const qreal maxSanePoint = 1e6;
382 QPointF controlTarget1;
383 QPointF controlTarget2;
386 QPointF controlDirection1 = pi1.
pos() + tangent1;
387 QPointF controlDirection2 = pi2.
pos() - tangent2;
390 QLineF line1(pi1.
pos(), controlDirection1);
391 QLineF line2(pi2.
pos(), controlDirection2);
395 QLineF line3(controlDirection1, controlDirection2);
396 QLineF line4(pi1.
pos(), pi2.
pos());
398 QPointF intersection;
399 if (line3.intersects(line4, &intersection) == QLineF::BoundedIntersection) {
400 qreal controlLength = line4.length() / 2;
402 line1.setLength(controlLength);
403 line2.setLength(controlLength);
405 controlTarget1 = line1.p2();
406 controlTarget2 = line2.p2();
408 QLineF::IntersectType type = line1.intersects(line2, &intersection);
410 if (type == QLineF::NoIntersection ||
411 intersection.manhattanLength() > maxSanePoint) {
413 intersection = 0.5 * (pi1.
pos() + pi2.
pos());
418 controlTarget1 = intersection;
419 controlTarget2 = intersection;
425 qreal velocity1 = QLineF(QPointF(), tangent1).length();
426 qreal velocity2 = QLineF(QPointF(), tangent2).length();
428 if (velocity1 == 0.0 || velocity2 == 0.0) {
431 warnKrita <<
"WARNING: Basic Smoothing: Velocity is Zero! Please report a bug:" <<
ppVar(velocity1) <<
ppVar(velocity2);
434 qreal similarity = qMin(velocity1/velocity2, velocity2/velocity1);
437 similarity = qMax(similarity, qreal(0.5));
441 coeff *= 1 - qMax(qreal(0.0), similarity - qreal(0.8));
449 if (velocity1 > velocity2) {
450 control1 = pi1.
pos() * (1.0 - coeff) + coeff * controlTarget1;
452 control2 = pi2.
pos() * (1.0 - coeff) + coeff * controlTarget2;
454 control2 = pi2.
pos() * (1.0 - coeff) + coeff * controlTarget2;
456 control1 = pi1.
pos() * (1.0 - coeff) + coeff * controlTarget1;
467 qreal zoomingCoeff = 1.0;
525 prevPos = prevPi.
pos();
530 qreal currentDistance = QVector2D(info.
pos() - prevPos).length();
542 qreal gaussianWeight = 1 / (sqrt(2 *
M_PI) * sigma);
543 qreal gaussianWeight2 = sigma * sigma;
544 qreal distanceSum = 0.0;
545 qreal scaleSum = 0.0;
546 qreal pressure = 0.0;
547 qreal baseRate = 0.0;
551 for (
int i =
m_d->
history.size() - 1; i >= 0; i--) {
558 qreal pressureGrad = 0.0;
559 if (i < m_d->history.size() - 1) {
564 if (pressureGrad > 0.0 ) {
565 pressureGrad *= tailAggressiveness * (1.0 - nextInfo.
pressure());
566 distance += pressureGrad * 3.0 * sigma;
570 if (gaussianWeight2 != 0.0) {
572 rate = gaussianWeight * exp(-distanceSum * distanceSum / (2 * gaussianWeight2));
577 }
else if (baseRate / rate > 100) {
582 x += rate * nextInfo.
pos().x();
583 y += rate * nextInfo.
pos().y();
586 pressure += rate * nextInfo.
pressure();
590 if (scaleSum != 0.0) {
595 pressure /= scaleSum;
599 if ((x != 0.0 && y != 0.0) || (x == info.
pos().x() && y == info.
pos().y())) {
600 info.
setPos(QPointF(x, y));
781 sampleSize = qMax(3, sampleSize);
785 for (
int i = sampleSize; i > 0; i--) {
796 if (delayedPaintEnabled) {
810 lastPaintInfo.
xTilt(),
811 lastPaintInfo.
yTilt(),
822 if (queue.size() > 1) {
823 QQueue<KisPaintInformation>::const_iterator it = queue.constBegin();
824 QQueue<KisPaintInformation>::const_iterator end = queue.constEnd();
834 qreal k = qreal(i - 1) / i;
835 result.KisPaintInformation::mixOtherWithoutTime(k, *it);
841 qreal k = qreal(i - 1) / i;
842 result.KisPaintInformation::mixOtherOnlyPosition(k, *it);
859 for (; it != end; ++it) {
862 bool canPaint =
true;
869 qreal dx = sqrt(
pow2(diff.x()) +
pow2(diff.y()));
885 delayedPaintTodoItems.append(newInfo);
994 return qMax(1, qFloor(realInterval));
1028 const QPointF &control1,
1029 const QPointF &control2,
1033#ifdef DEBUG_BEZIER_CURVES
1060 pi1, control1, control2, pi2));
1082 const QPointF &control1,
1083 const QPointF &control2,
Eigen::Matrix< double, 4, 2 > R
qreal distance(const QPointF &p1, const QPointF &p2)
@ SupportsContinuedInterstrokeData
void cancelUpdateStream()
void startUpdateStream(KisStrokesFacade *strokesFacade, KisStrokeId strokeId)
int stabilizerSampleSize(bool defaultValue=false) const
bool stabilizerDelayedPaint(bool defaultValue=false) const
void addEllipse(const QPointF ¢er, qreal rx, qreal ry)
void reset(const QPointF &pt)
QPointF pushThroughHistory(const QPointF &pt, qreal zoom)
The KisResourcesSnapshot class takes a snapshot of the various resources like colors and settings use...
void setCurrentNode(KisNodeSP node)
KisPaintOpPresetSP currentPaintOpPreset() const
qreal effectiveZoom() const
qreal airbrushingInterval() const
bool needsAirbrushing() const
bool presetNeedsAsynchronousUpdates() const
bool needsSpacingUpdates() const
void addEvent(const KisPaintInformation &pi)
void addFinishingEvent(int numSamples)
std::pair< iterator, iterator > range() const
void setUpdateOutlineCallback(std::function< void()> requestUpdateOutline)
void update(const QVector< KisPaintInformation > &newPaintInfos)
void setPaintLineCallback(std::function< void(const KisPaintInformation &, const KisPaintInformation &)> paintLine)
bool hasLastPaintInformation() const
void start(const KisPaintInformation &firstPaintInfo)
KisPaintInformation lastPaintInformation() const
virtual KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy)=0
virtual void endStroke(KisStrokeId id)=0
virtual void addJob(KisStrokeId id, KisStrokeJobData *data)=0
virtual bool cancelStroke(KisStrokeId id)=0
QVariant resource(int key) const
bool isTouchEvent() const
QSharedPointer< KisSmoothingOptions > KisSmoothingOptionsSP
qreal directionBetweenPoints(const QPointF &p1, const QPointF &p2, qreal defaultAngle)
@ EffectiveZoom
-Used only by painting tools for non-displaying purposes
@ EffectivePhysicalZoom
-Used by tool for displaying purposes
static KisUpdateTimeMonitor * instance()
void reportMouseMove(const QPointF &pos)