Krita Source Code Documentation
Loading...
Searching...
No Matches
KisStrokeSpeedMeasurer.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2017 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
8
9#include <QQueue>
10#include <QVector>
11
12#include "kis_global.h"
13
15{
16 struct StrokeSample {
18 StrokeSample(int _time, qreal _distance) : time(_time), distance(_distance) {}
19
20 int time = 0; /* ms */
21 qreal distance = 0;
22 };
23
25
28 int startTime = 0;
29
30 qreal maxSpeed = 0;
31
32 void purgeOldSamples();
33 void addSampleImpl(const QPointF &pt, int time);
34};
35
37 : m_d(new Private())
38{
39 m_d->timeSmoothWindow = timeSmoothWindow;
40}
41
45
46void KisStrokeSpeedMeasurer::Private::addSampleImpl(const QPointF &pt, int time)
47{
48 if (samples.isEmpty()) {
49 lastSamplePos = pt;
50 startTime = time;
51 samples.append(Private::StrokeSample(time, 0));
52 } else {
53 Private::StrokeSample &lastSample = samples.last();
54
55 const qreal newStrokeDistance = lastSample.distance + kisDistance(lastSamplePos, pt);
56 lastSamplePos = pt;
57
58 if (lastSample.time >= time) {
59 lastSample.distance = newStrokeDistance;
60 } else {
61 samples.append(Private::StrokeSample(time, newStrokeDistance));
62 }
63 }
64}
65
66void KisStrokeSpeedMeasurer::addSample(const QPointF &pt, int time)
67{
68 m_d->addSampleImpl(pt, time);
69 m_d->purgeOldSamples();
71}
72
74{
75 const int lastSampleTime = !m_d->samples.isEmpty() ? m_d->samples.last().time : 0;
76
77 const int timeSmoothBase = qMin(lastSampleTime, time);
78 const qreal timeSmoothStep = qreal(time - timeSmoothBase) / points.size();
79
80 for (int i = 0; i < points.size(); i++) {
81 const int sampleTime = timeSmoothBase + timeSmoothStep * (i + 1);
82 m_d->addSampleImpl(points[i], sampleTime);
83 }
84
85 m_d->purgeOldSamples();
87}
88
90{
91 if (m_d->samples.isEmpty()) return 0;
92
93 const Private::StrokeSample &lastSample = m_d->samples.last();
94
95 const int timeDiff = lastSample.time - m_d->startTime;
96 if (!timeDiff) return 0;
97
99
100 return lastSample.distance / timeDiff;
101}
102
104{
105 if (samples.size() <= 1) return;
106
107 const Private::StrokeSample lastSample = samples.last();
108
109 auto lastValueToKeep = samples.end();
110
111 for (auto it = samples.begin(); it != samples.end(); ++it) {
112 KIS_SAFE_ASSERT_RECOVER_RETURN(lastSample.time - it->time >= 0);
113
114 if (lastSample.time - it->time < timeSmoothWindow) break;
115 lastValueToKeep = it;
116 }
117
118 if (lastValueToKeep != samples.begin() &&
119 lastValueToKeep != samples.end()) {
120
121 samples.erase(samples.begin(), lastValueToKeep - 1);
122 }
123}
124
126{
127 if (m_d->samples.size() <= 1) return 0;
128
129 const Private::StrokeSample firstSample = m_d->samples.first();
130 const Private::StrokeSample lastSample = m_d->samples.last();
131
132 const int timeDiff = lastSample.time - firstSample.time;
133 if (!timeDiff) return 0;
134
136
137 return (lastSample.distance - firstSample.distance) / timeDiff;
138}
139
141{
142 return m_d->maxSpeed;
143}
144
146{
147 m_d->samples.clear();
148 m_d->lastSamplePos = QPointF();
149 m_d->startTime = 0;
150 m_d->maxSpeed = 0;
151}
152
154{
155 if (m_d->samples.size() <= 1) return;
156
157 const Private::StrokeSample firstSample = m_d->samples.first();
158 const Private::StrokeSample lastSample = m_d->samples.last();
159
160 const int timeDiff = lastSample.time - firstSample.time;
161 if (timeDiff < m_d->timeSmoothWindow) return;
162
163 const qreal speed = currentSpeed();
164 if (speed > m_d->maxSpeed) {
165 m_d->maxSpeed = speed;
166 }
167}
KisStrokeSpeedMeasurer(int timeSmoothWindow)
void addSample(const QPointF &pt, int time)
void addSamples(const QVector< QPointF > &points, int time)
const QScopedPointer< Private > m_d
#define KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(cond, val)
Definition kis_assert.h:129
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
qreal kisDistance(const QPointF &pt1, const QPointF &pt2)
Definition kis_global.h:190
void addSampleImpl(const QPointF &pt, int time)