blob: 9146b9539892c98c99a9882165dbcf1a1704e73e [file] [log] [blame]
/*
* Copyright (C) 2008-2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.gesture.recognizer;
import android.graphics.PointF;
import com.android.gesture.Gesture;
import java.util.Iterator;
/**
*
* Utilities for recognition.
*/
public class RecognitionUtil {
/**
* Re-sample a list of points to a given number
* @param stk
* @param num
* @return
*/
public static float[] resample(Gesture gesture, int num) {
final float increment = gesture.getLength()/(num - 1);
float[] newstk = new float[num*2];
float distanceSoFar = 0;
Iterator<PointF> it = gesture.getPoints().iterator();
PointF lstPoint = it.next();
int index = 0;
PointF currentPoint = null;
try
{
newstk[index] = lstPoint.x;
index++;
newstk[index] = lstPoint.y;
index++;
while (it.hasNext()) {
if (currentPoint == null)
currentPoint = it.next();
float deltaX = currentPoint.x - lstPoint.x;
float deltaY = currentPoint.y - lstPoint.y;
float distance = (float)Math.sqrt(deltaX*deltaX+deltaY*deltaY);
if (distanceSoFar+distance >= increment) {
float ratio = (increment - distanceSoFar) / distance;
float nx = lstPoint.x + ratio * deltaX;
float ny = lstPoint.y + ratio * deltaY;
newstk[index] = nx;
index++;
newstk[index] = ny;
index++;
lstPoint = new PointF(nx, ny);
distanceSoFar = 0;
}
else {
lstPoint = currentPoint;
currentPoint = null;
distanceSoFar += distance;
}
}
}
catch(Exception ex) {
ex.printStackTrace();
}
for(int i = index; i < newstk.length -1; i+=2) {
newstk[i] = lstPoint.x;
newstk[i+1] = lstPoint.y;
}
return newstk;
}
/**
* Calculate the centroid of a list of points
* @param points
* @return the centroid
*/
public static PointF computeCentroid(float[] points) {
float centerX = 0;
float centerY = 0;
for(int i=0; i<points.length; i++)
{
centerX += points[i];
i++;
centerY += points[i];
}
centerX = 2 * centerX/points.length;
centerY = 2 * centerY/points.length;
return new PointF(centerX, centerY);
}
/**
* calculate the variance-covariance matrix, treat each point as a sample
* @param points
* @return
*/
public static double[][] computeCoVariance(float[] points) {
double[][] array = new double[2][2];
array[0][0] = 0;
array[0][1] = 0;
array[1][0] = 0;
array[1][1] = 0;
for(int i=0; i<points.length; i++)
{
float x = points[i];
i++;
float y = points[i];
array[0][0] += x * x;
array[0][1] += x * y;
array[1][0] = array[0][1];
array[1][1] += y * y;
}
array[0][0] /= (points.length/2);
array[0][1] /= (points.length/2);
array[1][0] /= (points.length/2);
array[1][1] /= (points.length/2);
return array;
}
public static float computeTotalLength(float[] points) {
float sum = 0;
for (int i=0; i<points.length - 4; i+=2) {
float dx = points[i+2] - points[i];
float dy = points[i+3] - points[i+1];
sum += Math.sqrt(dx*dx + dy*dy);
}
return sum;
}
public static double computeStraightness(float[] points) {
float totalLen = computeTotalLength(points);
float dx = points[2] - points[0];
float dy = points[3] - points[1];
return Math.sqrt(dx*dx + dy*dy) / totalLen;
}
public static double computeStraightness(float[] points, float totalLen) {
float dx = points[2] - points[0];
float dy = points[3] - points[1];
return Math.sqrt(dx*dx + dy*dy) / totalLen;
}
public static double averageEuclidDistance(float[] stk1, float[] stk2) {
double distance = 0;
for (int i = 0; i < stk1.length; i += 2) {
distance += PointF.length(stk1[i] - stk2[i], stk1[i+1] - stk2[i+1]);
}
return distance/stk1.length;
}
public static double squaredEuclidDistance(float[] stk1, float[] stk2) {
double squaredDistance = 0;
for (int i = 0; i < stk1.length; i++) {
float difference = stk1[i] - stk2[i];
squaredDistance += difference * difference;
}
return squaredDistance/stk1.length;
}
/**
* Calculate the cosine distance between two instances
* @param in1
* @param in2
* @return the angle between 0 and Math.PI
*/
public static double cosineDistance(Instance in1, Instance in2) {
float sum = 0;
for (int i = 0; i < in1.vector.length; i++) {
sum += in1.vector[i] * in2.vector[i];
}
return Math.acos(sum / (in1.length * in2.length));
}
}