/** * Compute the current velocity based on the points that have been collected. Only call this when * you actually want to retrieve velocity information, as it is relatively expensive. You can then * retrieve the velocity with {@link #getXVelocity()} and {@link #getYVelocity()}. * * @param units The units you would like the velocity in. A value of 1 provides pixels per * millisecond, 1000 provides pixels per second, etc. * @param maxVelocity The maximum velocity that can be computed by this method. This value must be * declared in the same unit as the units parameter. This value must be positive. */ public void computeCurrentVelocity(int units, float maxVelocity) { final int lastTouchIndex = mLastTouchIndex; for (Pointer pointer = mPointerListHead; pointer != null; pointer = pointer.next) { final long[] pastTime = pointer.pastTime; // Search backwards in time for oldest acceptable time. // Stop at the beginning of the trace as indicated by the sentinel time Long.MIN_VALUE. int oldestTouchIndex = lastTouchIndex; int numTouches = 1; final long minTime = pastTime[lastTouchIndex] - MAX_AGE_MILLISECONDS; while (numTouches < NUM_PAST) { final int nextOldestTouchIndex = (oldestTouchIndex + NUM_PAST - 1) % NUM_PAST; final long nextOldestTime = pastTime[nextOldestTouchIndex]; if (nextOldestTime < minTime) { // also handles end of trace sentinel break; } oldestTouchIndex = nextOldestTouchIndex; numTouches += 1; } // If we have a lot of samples, skip the last received sample since it is // probably pretty noisy compared to the sum of all of the traces already acquired. if (numTouches > 3) { numTouches -= 1; } // Kind-of stupid. final float[] pastX = pointer.pastX; final float[] pastY = pointer.pastY; final float oldestX = pastX[oldestTouchIndex]; final float oldestY = pastY[oldestTouchIndex]; final long oldestTime = pastTime[oldestTouchIndex]; float accumX = 0; float accumY = 0; for (int i = 1; i < numTouches; i++) { final int touchIndex = (oldestTouchIndex + i) % NUM_PAST; final int duration = (int) (pastTime[touchIndex] - oldestTime); if (duration == 0) continue; float delta = pastX[touchIndex] - oldestX; float velocity = (delta / duration) * units; // pixels/frame. accumX = (accumX == 0) ? velocity : (accumX + velocity) * .5f; delta = pastY[touchIndex] - oldestY; velocity = (delta / duration) * units; // pixels/frame. accumY = (accumY == 0) ? velocity : (accumY + velocity) * .5f; } if (accumX < -maxVelocity) { accumX = -maxVelocity; } else if (accumX > maxVelocity) { accumX = maxVelocity; } if (accumY < -maxVelocity) { accumY = -maxVelocity; } else if (accumY > maxVelocity) { accumY = maxVelocity; } pointer.xVelocity = accumX; pointer.yVelocity = accumY; if (localLOGV) { Log.v( TAG, "Pointer " + pointer.id + ": Y velocity=" + accumX + " X velocity=" + accumY + " N=" + numTouches); } } }