Added the Protractor algorithm for calculating the minimum cosine distance between gestures
diff --git a/core/java/android/gesture/GestureStore.java b/core/java/android/gesture/GestureStore.java
index 5f1a445..11a94d1 100644
--- a/core/java/android/gesture/GestureStore.java
+++ b/core/java/android/gesture/GestureStore.java
@@ -65,7 +65,12 @@
 
     // 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 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);
     }
 
     /**
diff --git a/core/java/android/gesture/GestureUtilities.java b/core/java/android/gesture/GestureUtilities.java
index 40d7029..f1dcd89 100755
--- a/core/java/android/gesture/GestureUtilities.java
+++ b/core/java/android/gesture/GestureUtilities.java
@@ -366,6 +366,38 @@
         }
         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);
diff --git a/core/java/android/gesture/Instance.java b/core/java/android/gesture/Instance.java
index ef208ac..68a2985 100755
--- a/core/java/android/gesture/Instance.java
+++ b/core/java/android/gesture/Instance.java
@@ -94,7 +94,7 @@
         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;
diff --git a/core/java/android/gesture/InstanceLearner.java b/core/java/android/gesture/InstanceLearner.java
index b93b76f..9987e69 100644
--- a/core/java/android/gesture/InstanceLearner.java
+++ b/core/java/android/gesture/InstanceLearner.java
@@ -41,7 +41,7 @@
     };
 
     @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 @@
             }
             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);
             }
diff --git a/core/java/android/gesture/Learner.java b/core/java/android/gesture/Learner.java
index feacde5..60997e0 100755
--- a/core/java/android/gesture/Learner.java
+++ b/core/java/android/gesture/Learner.java
@@ -79,5 +79,5 @@
         instances.removeAll(toDelete);
     }
 
-    abstract ArrayList<Prediction> classify(int gestureType, float[] vector);
+    abstract ArrayList<Prediction> classify(int sequenceType, int orientationType, float[] vector);
 }