Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e96b6838 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change I4758f121 into eclair-mr2

* changes:
  Added the Protractor algorithm for calculating the minimum cosine distance between gestures
parents 492604e9 4758f121
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -65,7 +65,12 @@ public class GestureStore {

    // ORIENTATION_SENSITIVE and ORIENTATION_INVARIANT are only for SEQUENCE_SENSITIVE gestures
    public static final int ORIENTATION_INVARIANT = 1;
    // at most 2 directions can be recognized
    public static final int ORIENTATION_SENSITIVE = 2;
    // at most 4 directions can be recognized
    static final int ORIENTATION_SENSITIVE_4 = 4;
    // at most 8 directions can be recognized
    static final int ORIENTATION_SENSITIVE_8 = 8;

    private static final short FILE_FORMAT_VERSION = 1;

@@ -131,7 +136,7 @@ public class GestureStore {
    public ArrayList<Prediction> recognize(Gesture gesture) {
        Instance instance = Instance.createInstance(mSequenceType,
                mOrientationStyle, gesture, null);
        return mClassifier.classify(mSequenceType, instance.vector);
        return mClassifier.classify(mSequenceType, mOrientationStyle, instance.vector);
    }

    /**
+32 −0
Original line number Diff line number Diff line
@@ -367,6 +367,38 @@ final class GestureUtilities {
        return Math.acos(sum);
    }
    
    /**
     * Calculate the "minimum" cosine distance between two instances
     * 
     * @param vector1
     * @param vector2
     * @param numOrientations the maximum number of orientation allowed
     * @return the distance between the two instances (between 0 and Math.PI)
     */
    static double minimumCosineDistance(float[] vector1, float[] vector2, int numOrientations) {
        final int len = vector1.length;
        double a = 0;
        double b = 0;
        for (int i = 0; i < len; i += 2) {
            a += vector1[i] * vector2[i] + vector1[i + 1] * vector2[i + 1];
            b += vector1[i] * vector2[i + 1] - vector1[i + 1] * vector2[i];
        }
        if (a != 0) {
            final double tan = b/a;
            final double angle = Math.atan(tan);
            if (numOrientations > 2 && Math.abs(angle) >= Math.PI / numOrientations) {
                return Math.acos(a);
            } else {
                final double cosine = Math.cos(angle);
                final double sine = cosine * tan; 
                return Math.acos(a * cosine + b * sine);
            }
        } else {
            return Math.PI / 2;
        }
    }


    static OrientedBoundingBox computeOrientedBoundingBox(ArrayList<GesturePoint> pts) {
        GestureStroke stroke = new GestureStroke(pts);
        float[] points = temporalSampling(stroke, TEMPORAL_SAMPLING_RATE);
+1 −1
Original line number Diff line number Diff line
@@ -94,7 +94,7 @@ class Instance {
        float orientation = (float)Math.atan2(pts[1] - center[1], pts[0] - center[0]);

        float adjustment = -orientation;
        if (orientationType == GestureStore.ORIENTATION_SENSITIVE) {
        if (orientationType != GestureStore.ORIENTATION_INVARIANT) {
            int count = ORIENTATIONS.length;
            for (int i = 0; i < count; i++) {
                float delta = ORIENTATIONS[i] - orientation;
+2 −2
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ class InstanceLearner extends Learner {
    };

    @Override
    ArrayList<Prediction> classify(int sequenceType, float[] vector) {
    ArrayList<Prediction> classify(int sequenceType, int orientationType, float[] vector) {
        ArrayList<Prediction> predictions = new ArrayList<Prediction>();
        ArrayList<Instance> instances = getInstances();
        int count = instances.size();
@@ -53,7 +53,7 @@ class InstanceLearner extends Learner {
            }
            double distance;
            if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) {
                distance = GestureUtilities.cosineDistance(sample.vector, vector);
                distance = GestureUtilities.minimumCosineDistance(sample.vector, vector, orientationType);
            } else {
                distance = GestureUtilities.squaredEuclideanDistance(sample.vector, vector);
            }
+1 −1
Original line number Diff line number Diff line
@@ -79,5 +79,5 @@ abstract class Learner {
        instances.removeAll(toDelete);
    }

    abstract ArrayList<Prediction> classify(int gestureType, float[] vector);
    abstract ArrayList<Prediction> classify(int sequenceType, int orientationType, float[] vector);
}