[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [calligra/krita-testing-kazakov] krita/ui/tool: Make the Weighted Smoothing algorithm use 'distance'
From:       Dmitry Kazakov <dimula73 () gmail ! com>
Date:       2013-11-04 7:50:39
Message-ID: E1VdEvn-0005m7-G0 () scm ! kde ! org
[Download RAW message or body]

Git commit c5162f9fbb295e8b2566ac3975f625dbcdd7257a by Dmitry Kazakov.
Committed on 04/11/2013 at 07:50.
Pushed by dkazakov into branch 'krita-testing-kazakov'.

Make the Weighted Smoothing algorithm use 'distance' instead of 'velocity'

The time measurements of the tablet events are really unstable,
especially when using openGL canvas, which causes the Weighted Smoothing
processed lines bended and waggy. This patch makes the algorithm use
distance parameter instead of the velocity parameter, which does not
depend on time, so does not fluctuate so drastically.

BUG:326512

M  +32   -21   krita/ui/tool/kis_tool_freehand_helper.cpp

http://commits.kde.org/calligra/c5162f9fbb295e8b2566ac3975f625dbcdd7257a

diff --git a/krita/ui/tool/kis_tool_freehand_helper.cpp \
b/krita/ui/tool/kis_tool_freehand_helper.cpp index 97d36a3..78bccfa 100644
--- a/krita/ui/tool/kis_tool_freehand_helper.cpp
+++ b/krita/ui/tool/kis_tool_freehand_helper.cpp
@@ -64,7 +64,7 @@ struct KisToolFreehandHelper::Private
     QTimer airbrushingTimer;
 
     QList<KisPaintInformation> history;
-    QList<qreal> velocityHistory;
+    QList<qreal> distanceHistory;
 };
 
 
@@ -138,7 +138,7 @@ void KisToolFreehandHelper::initPaint(KoPointerEvent *event,
     m_d->strokeId = m_d->strokesFacade->startStroke(stroke);
 
     m_d->history.clear();
-    m_d->velocityHistory.clear();
+    m_d->distanceHistory.clear();
 
     if(m_d->resources->needsAirbrushing()) {
         m_d->airbrushingTimer.setInterval(m_d->resources->airbrushingRate());
@@ -243,28 +243,40 @@ void KisToolFreehandHelper::paint(KoPointerEvent *event)
             m_d->infoBuilder->continueStroke(event,
                                              m_d->strokeTime.elapsed());
 
-    // Smooth the coordinates out using the history and the velocity. See
-    // https://bugs.kde.org/show_bug.cgi?id=281267 and \
                http://www24.atwiki.jp/sigetch_2007/pages/17.html.
-    // This is also implemented in gimp, which is where I cribbed the code from.
+    /**
+     * Smooth the coordinates out using the history and the
+     * distance. This is a heavily modified version of an algo used in
+     * Gimp and described in https://bugs.kde.org/show_bug.cgi?id=281267 and
+     * http://www24.atwiki.jp/sigetch_2007/pages/17.html.  The main
+     * differences are:
+     *
+     * 1) It uses 'distance' instead of 'velocity', since time
+     *    measurements are too unstable in realworld environment
+     *
+     * 2) There is no 'Quality' parameter, since the number of samples
+     *    is calculated automatically
+     *
+     * 3) 'Tail Aggressiveness' is used for controling the end of the
+     *    stroke
+     *
+     * 4) The formila is a little bit different: 'Distance' parameter
+     *    stands for $3 \Sigma$
+     */
     if (m_d->smoothingOptions.smoothingType == \
KisSmoothingOptions::WEIGHTED_SMOOTHING  && m_d->smoothingOptions.smoothnessDistance \
> 0.0) {  
-        { // initialize current velocity
+        { // initialize current distance
             QPointF prevPos;
-            int prevTime;
 
             if (!m_d->history.isEmpty()) {
                 const KisPaintInformation &prevPi = m_d->history.last();
                 prevPos = prevPi.pos();
-                prevTime = prevPi.currentTime();
             } else {
                 prevPos = m_d->previousPaintInformation.pos();
-                prevTime = m_d->previousPaintInformation.currentTime();
             }
 
-            int deltaTime = qMax(1, info.currentTime() - prevTime); // make sure \
                deltaTime > 1
-            qreal currentVelocity = QVector2D(info.pos() - prevPos).length() / \
                deltaTime;
-            m_d->velocityHistory.append(currentVelocity);
+            qreal currentDistance = QVector2D(info.pos() - prevPos).length();
+            m_d->distanceHistory.append(currentDistance);
         }
 
         m_d->history.append(info);
@@ -273,24 +285,23 @@ void KisToolFreehandHelper::paint(KoPointerEvent *event)
         qreal y = 0.0;
 
         if (m_d->history.size() > 3) {
-            const qreal avg_events_rate = 8; // ms
-            const qreal sigma = m_d->smoothingOptions.smoothnessDistance / (3.0 * \
avg_events_rate); // '3.0' for (3 * sigma) range +            const qreal sigma = \
m_d->smoothingOptions.smoothnessDistance / 3.0; // '3.0' for (3 * sigma) range  
             qreal gaussianWeight = 1 / (sqrt(2 * M_PI) * sigma);
             qreal gaussianWeight2 = sigma * sigma;
-            qreal velocitySum = 0.0;
+            qreal distanceSum = 0.0;
             qreal scaleSum = 0.0;
             qreal pressure = 0.0;
             qreal baseRate = 0.0;
 
-            Q_ASSERT(m_d->history.size() == m_d->velocityHistory.size());
+            Q_ASSERT(m_d->history.size() == m_d->distanceHistory.size());
 
             for (int i = m_d->history.size() - 1; i >= 0; i--) {
                 qreal rate = 0.0;
 
                 const KisPaintInformation nextInfo = m_d->history.at(i);
-                double velocity = m_d->velocityHistory.at(i);
-                Q_ASSERT(velocity >= 0.0);
+                double distance = m_d->distanceHistory.at(i);
+                Q_ASSERT(distance >= 0.0);
 
                 qreal pressureGrad = 0.0;
                 if (i < m_d->history.size() - 1) {
@@ -300,13 +311,13 @@ void KisToolFreehandHelper::paint(KoPointerEvent *event)
 
                     if (pressureGrad > 0.0 ) {
                         pressureGrad *= tailAgressiveness * (1.0 - \
                nextInfo.pressure());
-                        velocity += pressureGrad * 3.0 * sigma; // (3 * sigma) --- \
holds > 90% of the region +                        distance += pressureGrad * 3.0 * \
sigma; // (3 * sigma) --- holds > 90% of the region  }
                 }
 
                 if (gaussianWeight2 != 0.0) {
-                    velocitySum += velocity;
-                    rate = gaussianWeight * exp(-velocitySum * velocitySum / (2 * \
gaussianWeight2)); +                    distanceSum += distance;
+                    rate = gaussianWeight * exp(-distanceSum * distanceSum / (2 * \
gaussianWeight2));  }
 
                 if (m_d->history.size() - i == 1) {


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic