9 #include "kineticmodel.h"
12 #include <QElapsedTimer>
14 static const int KineticModelDefaultUpdateInterval = 15;
16 class KineticModelPrivate
25 qreal velocityHeading;
27 qreal deaccelerationHeading;
32 bool changingPosition;
34 KineticModelPrivate();
37 KineticModelPrivate::KineticModelPrivate()
43 , deacceleration(0, 0)
44 , deaccelerationHeading(0)
47 , changingPosition(true)
52 KineticModel::KineticModel(
QObject *parent)
54 , d_ptr(new KineticModelPrivate)
57 d_ptr->ticker.setInterval(KineticModelDefaultUpdateInterval);
60 KineticModel::~KineticModel()
65 bool KineticModel::hasVelocity()
const
67 return !d_ptr->velocity.isNull();
70 int KineticModel::duration()
const
72 return d_ptr->duration;
75 void KineticModel::setDuration(
int ms)
80 QPointF KineticModel::position()
const
82 return d_ptr->position;
85 void KineticModel::setPosition(
const QPointF& position)
87 setPosition( position.
x(), position.
y() );
90 void KineticModel::setPosition(qreal posX, qreal posY)
92 d_ptr->position.setX( posX );
93 d_ptr->position.setY( posY );
95 int elapsed = d_ptr->timestamp.elapsed();
98 if (elapsed < d_ptr->ticker.interval() / 2) {
102 qreal delta =
static_cast<qreal
>( elapsed ) / 1000.0;
104 QPointF lastSpeed = d_ptr->velocity;
105 QPointF currentSpeed = ( d_ptr->position - d_ptr->lastPosition ) / delta;
106 d_ptr->velocity = 0.2 * lastSpeed + 0.8 * currentSpeed;
107 d_ptr->lastPosition = d_ptr->position;
109 d_ptr->changingPosition =
true;
110 d_ptr->timestamp.start();
113 void KineticModel::setHeading(qreal heading)
115 d_ptr->heading = heading;
117 int elapsed = d_ptr->timestamp.elapsed();
118 qreal delta =
static_cast<qreal
>( elapsed ) / 1000.0;
120 qreal lastSpeed = d_ptr->velocityHeading;
121 qreal currentSpeed = delta ? ( d_ptr->heading - d_ptr->lastHeading ) / delta : 0;
122 d_ptr->velocityHeading = 0.5 * lastSpeed + 0.2 * currentSpeed;
123 d_ptr->lastHeading = d_ptr->heading;
125 d_ptr->changingPosition =
false;
126 d_ptr->timestamp.start();
129 void KineticModel::jumpToPosition(
const QPointF& position)
131 jumpToPosition( position.
x(), position.
y() );
134 void KineticModel::jumpToPosition(qreal posX, qreal posY)
136 d_ptr->position.setX( posX );
137 d_ptr->position.setY( posY );
140 int KineticModel::updateInterval()
const
142 return d_ptr->ticker.interval();
145 void KineticModel::setUpdateInterval(
int ms)
147 d_ptr->ticker.setInterval(ms);
155 d->timestamp.start();
157 d->velocityHeading = 0;
165 const int elapsed = d->timestamp.elapsed();
166 if ( elapsed > 2 * d->ticker.interval() ) {
172 d->deacceleration = d->velocity * 1000 / ( 1 + d_ptr->duration );
173 if (d->deacceleration.x() < 0) {
174 d->deacceleration.setX( -d->deacceleration.x() );
176 if (d->deacceleration.y() < 0) {
177 d->deacceleration.setY( -d->deacceleration.y() );
180 d->deaccelerationHeading = qAbs(d->velocityHeading) * 1000 / ( 1 + d_ptr->duration );
182 if (!d->ticker.isActive())
186 void KineticModel::update()
190 int elapsed = qMin(
static_cast<int>(d->timestamp.elapsed()), 100 );
191 qreal delta =
static_cast<qreal
>(elapsed) / 1000.0;
194 if (d->changingPosition) {
195 d->position += d->velocity * delta;
196 QPointF vstep = d->deacceleration * delta;
198 if (d->velocity.x() < vstep.
x() && d->velocity.x() >= -vstep.
x()) {
199 d->velocity.
setX( 0 );
201 if (d->velocity.x() > 0)
202 d->velocity.setX( d->velocity.x() - vstep.
x() );
204 d->velocity.setX( d->velocity.x() + vstep.
x() );
207 if (d->velocity.y() < vstep.
y() && d->velocity.y() >= -vstep.
y()) {
208 d->velocity.setY( 0 );
210 if (d->velocity.y() > 0)
211 d->velocity.setY( d->velocity.y() - vstep.
y() );
213 d->velocity.setY( d->velocity.y() + vstep.
y() );
216 stop = d->velocity.isNull();
218 emit positionChanged( d->position.x(), d->position.y() );
220 d->heading += d->velocityHeading * delta;
221 qreal vstep = d->deaccelerationHeading * delta;
222 if ((d->velocityHeading < vstep && d->velocityHeading >= -vstep) || !vstep) {
223 d->velocityHeading = 0;
225 d->velocityHeading += d->velocityHeading > 0 ? -1 * vstep : vstep;
228 stop = !d->velocityHeading;
230 emit headingChanged( d->heading );
238 d->timestamp.start();
241 #include "moc_kineticmodel.cpp"