Calculating scroll inertia/momentum?

What I've done with good results is the following.

On each mouse drag event (or touch event), you store the velocity (so the amount of movement divided by the time since the last frame) and a timestamp. You only need the last one, so that's just two variables.

When the mouse/touch is released, check to see if the last timestamp is recent enough (I use 0.3 seconds). If so, set a variable inertialVelocity to the last calculated velocity; otherwise set it to 0 to prevent scrolling if the user carefully selected a position.

Then on every update (either through a timer, or each render call, depending on how you're rendering), scroll by inertialVelocity * INERTIA_SCROLL_FACTOR (I use 0.9) and multiply inertialVelocity by INERTIA_ACCELERATION (I use 0.98).

You'll probably want to add a threshold, so scrolling stops if inertialVelocity becomes too small. I use 1 as a threshold, as my rendering lib uses floats as coordinates. If coordinates are integrals, it'll drop to zero by itself.

One thing to keep in mind is that inertialVelocity can be either positive or negative, depending on the direction.

So, in pseudo code:

OnMouseMove:
    inertialVelocity = moveDistance / (now - timeOfLastEvent)
    timeOfLastEvent = now

OnMouseUp:
    if (now - timeSinceLastEvent > 0.3f)
        inertialVelocity = 0

OnTimer/OnRender:
    // timeDelta is needed only when doing this on render events, just to make
    // it independent of the render speed. It is the time since the previous render
    scrollPosition += inertialVelocity * INERTIA_SCROLL_FACTOR * timeDelta
    inertialVelocity *= INERTIA_ACCELERATION * timeDelta
    // Keep in mind that velocity can be negative as well, hence the abs
    if (abs(inertialVelocity) < INERTIA_THRESHOLD)
        inertialVelocity = 0

You could simulate this with a "recent axis changes" queue.

If you store say the last half a second of changes with the corresponding timestamps, you can then test if the queue is longer than a value N (ie if the user dragged it quicker than usual towards the end). You know the total distance traveled in the last half a second, the time, from those you can get a speed.

Scale the speed to something reasonable (say.. for 15px/.5sec, map to ~25px/sec) and apply a negative acceleration (also appropiately scaled, for the example above, say -20px/sec) every couple of milliseconds (or as fast as your system can easily handle it, don't overstress it with this).

Then run a timer, updating the speed at each tick (speed+=accel*time_scale), then the position (position+=speed*time_scale). When the speed reaches 0 (or goes below it) kill the timer.