Loading core/java/android/gesture/GestureStore.java +6 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } /** Loading core/java/android/gesture/GestureUtilities.java +32 −0 Original line number Diff line number Diff line Loading @@ -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); Loading core/java/android/gesture/Instance.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading core/java/android/gesture/InstanceLearner.java +2 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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); } Loading core/java/android/gesture/Learner.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading
core/java/android/gesture/GestureStore.java +6 −1 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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); } /** Loading
core/java/android/gesture/GestureUtilities.java +32 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
core/java/android/gesture/Instance.java +1 −1 Original line number Diff line number Diff line Loading @@ -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; Loading
core/java/android/gesture/InstanceLearner.java +2 −2 Original line number Diff line number Diff line Loading @@ -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(); Loading @@ -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); } Loading
core/java/android/gesture/Learner.java +1 −1 Original line number Diff line number Diff line Loading @@ -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); }