I'm trying to find a way to calculate the distance traveled during a Gesture. I can get the distance between two points using MotionEvent.ACTION_DOWN and MotionEvent.ACTION_UP or MotionEvent.ACTION_MOVE. But that doesn't account for moving in say, a circle. It would calculate 0 because you moved all the way back around. I'm looking for total distance traveled, preferably in pixels so I can manipulate it further, if needed.
Using the motion sensor, time how long is the user "walking" (obviously, there's no easy way to determine if your user is actually walking or just shaking the phone). Multiply this with your user's pace factor and you get a pretty rough idea of how much walking has your user done.
A "touch gesture" occurs when a user places one or more fingers on the touch screen, and your application interprets that pattern of touches as a particular gesture. There are correspondingly two phases to gesture detection: Gather data about touch events.
You can use the historic stuff of the MotionEvent. Based on the example of the API Doc you could do something like so (for simplicity my example doesn't deal with multi-touch):
On ACTION_MOVE and ACTION_UP do this, where startX
, startY
would be the last known coordinates, e.g. from last ACTION_DOWN event.
float getDistance(float startX, float startY, MotionEvent ev) {
float distanceSum = 0;
final int historySize = ev.getHistorySize();
for (int h = 0; h < historySize; h++) {
// historical point
float hx = ev.getHistoricalX(0, h);
float hy = ev.getHistoricalY(0, h);
// distance between startX,startY and historical point
float dx = (hx - startX);
float dy = (hy - startY);
distanceSum += Math.sqrt(dx * dx + dy * dy);
// make historical point the start point for next loop iteration
startX = hx;
startY = hy;
}
// add distance from last historical point to event's point
float dx = (ev.getX(0) - startX);
float dy = (ev.getY(0) - startY);
distanceSum += Math.sqrt(dx * dx + dy * dy);
return distanceSum;
}
A first order approximation would be to sum up the local length of every tiny piece of movement detected :
On ACTION_DOWN
total = 0;
xPrec = ev.getX();
yPrec = ev.getY();
On ACTION_MOVE
final float dx = ev.getX() - xPrec;
final float dy = ev.getY() - yPrec;
final float dl = sqrt(dx * dx + dy * dy);
total += dl;
xPrec = ev.getX();
yPrec = ev.getY();
On ACTION_UP
you can do whatever you want with total
which contains the total approximated length of your path.
If you read the official documentation about MotionEvent
http://developer.android.com/reference/android/view/MotionEvent.html you will see a section entitled Batching which explains that one given motion event can batch together multiple movement samples. For the best first order approximation you need to consume all those samples using
getHistorySize
, getHistoricalX
, getHistoricalY
. Don't forget to process the most recent sample which stands in getX
and getY
.
If you need a better approximation I suggest you to read about the problem of curve fitting http://en.wikipedia.org/wiki/Curve_fitting, but as the frequency of touch events is quite fast you may not need to do so and get satisfied with a first order approximation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With