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

Commit 4758f121 authored by Yang Li's avatar Yang Li
Browse files

Added the Protractor algorithm for calculating the minimum cosine distance between gestures

parent ba8e4d24
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);
}