Improved angles variance and added the angles percentage evaluation
Change-Id: I312529ea89707d27a7ef1a5ffd6d94427eaf6e8f
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
similarity index 62%
rename from packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
rename to packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
index c74339b..a6ebc0b 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/AnglesVarianceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesClassifier.java
@@ -32,17 +32,26 @@
* previously calculated angle. Then it calculates the variance of the differences from a stroke.
* To the differences there is artificially added value 0.0 and the difference between the first
* angle and PI (angles are in radians). It helps with strokes which have few points and punishes
- * more strokes which are not smooth. This classifier also tries to split the stroke into two parts
- * int the place in which the biggest angle is. It calculates the angle variance of the two parts
- * and sums them up. The reason the classifier is doing this, is because some human swipes at the
- * beginning go for a moment in one direction and then they rapidly change direction for the rest
- * of the stroke (like a tick). The final result is the minimum of angle variance of the whole
- * stroke and the sum of angle variances of the two parts split up.
+ * more strokes which are not smooth.
+ *
+ * This classifier also tries to split the stroke into two parts in the place in which the biggest
+ * angle is. It calculates the angle variance of the two parts and sums them up. The reason the
+ * classifier is doing this, is because some human swipes at the beginning go for a moment in one
+ * direction and then they rapidly change direction for the rest of the stroke (like a tick). The
+ * final result is the minimum of angle variance of the whole stroke and the sum of angle variances
+ * of the two parts split up. The classifier tries the tick option only if the first part is
+ * shorter than the second part.
+ *
+ * Additionally, the classifier classifies the angles as left angles (those angles which value is
+ * in [0.0, PI - ANGLE_DEVIATION) interval), straight angles
+ * ([PI - ANGLE_DEVIATION, PI + ANGLE_DEVIATION] interval) and right angles
+ * ((PI + ANGLE_DEVIATION, 2 * PI) interval) and then calculates the percentage of angles which are
+ * in the same direction (straight angles can be left angels or right angles)
*/
-public class AnglesVarianceClassifier extends StrokeClassifier {
+public class AnglesClassifier extends StrokeClassifier {
private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
- public AnglesVarianceClassifier(ClassifierData classifierData) {
+ public AnglesClassifier(ClassifierData classifierData) {
mClassifierData = classifierData;
}
@@ -66,10 +75,14 @@
@Override
public float getFalseTouchEvaluation(int type, Stroke stroke) {
- return AnglesVarianceEvaluator.evaluate(mStrokeMap.get(stroke).getAnglesVariance());
+ Data data = mStrokeMap.get(stroke);
+ return AnglesVarianceEvaluator.evaluate(data.getAnglesVariance())
+ + AnglesPercentageEvaluator.evaluate(data.getAnglesPercentage());
}
private static class Data {
+ private final float ANGLE_DEVIATION = (float) Math.PI / 20.0f;
+
private List<Point> mLastThreePoints = new ArrayList<>();
private float mFirstAngleVariance;
private float mPreviousAngle;
@@ -80,6 +93,12 @@
private float mSecondSum;
private float mCount;
private float mSecondCount;
+ private float mFirstLength;
+ private float mLength;
+ private float mAnglesCount;
+ private float mLeftAngles;
+ private float mRightAngles;
+ private float mStraightAngles;
public Data() {
mFirstAngleVariance = 0.0f;
@@ -88,6 +107,8 @@
mSumSquares = mSecondSumSquares = 0.0f;
mSum = mSecondSum = 0.0f;
mCount = mSecondCount = 1.0f;
+ mLength = mFirstLength = 0.0f;
+ mAnglesCount = mLeftAngles = mRightAngles = mStraightAngles = 0.0f;
}
public void addPoint(Point point) {
@@ -95,6 +116,9 @@
// Repetitions are being ignored so that proper angles are calculated.
if (mLastThreePoints.isEmpty()
|| !mLastThreePoints.get(mLastThreePoints.size() - 1).equals(point)) {
+ if (!mLastThreePoints.isEmpty()) {
+ mLength += mLastThreePoints.get(mLastThreePoints.size() - 1).dist(point);
+ }
mLastThreePoints.add(point);
if (mLastThreePoints.size() == 4) {
mLastThreePoints.remove(0);
@@ -102,6 +126,15 @@
float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
mLastThreePoints.get(2));
+ mAnglesCount++;
+ if (angle < Math.PI - ANGLE_DEVIATION) {
+ mLeftAngles++;
+ } else if (angle <= Math.PI + ANGLE_DEVIATION) {
+ mStraightAngles++;
+ } else {
+ mRightAngles++;
+ }
+
float difference = angle - mPreviousAngle;
// If this is the biggest angle of the stroke so then we save the value of
@@ -109,6 +142,7 @@
// variance of the second part.
if (mBiggestAngle < angle) {
mBiggestAngle = angle;
+ mFirstLength = mLength;
mFirstAngleVariance = getAnglesVariance(mSumSquares, mSum, mCount);
mSecondSumSquares = 0.0f;
mSecondSum = 0.0f;
@@ -132,9 +166,19 @@
}
public float getAnglesVariance() {
- return Math.min(getAnglesVariance(mSumSquares, mSum, mCount),
- mFirstAngleVariance + getAnglesVariance(mSecondSumSquares, mSecondSum,
- mSecondCount));
+ float anglesVariance = getAnglesVariance(mSumSquares, mSum, mCount);
+ if (mFirstLength < mLength / 2f) {
+ anglesVariance = Math.min(anglesVariance, mFirstAngleVariance
+ + getAnglesVariance(mSecondSumSquares, mSecondSum, mSecondCount));
+ }
+ return anglesVariance;
+ }
+
+ public float getAnglesPercentage() {
+ if (mAnglesCount == 0.0f) {
+ return 1.0f;
+ }
+ return (Math.max(mLeftAngles, mRightAngles) + mStraightAngles) / mAnglesCount;
}
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
new file mode 100644
index 0000000..a0ceb29
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/AnglesPercentageEvaluator.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 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.systemui.classifier;
+
+public class AnglesPercentageEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 1.00) evaluation++;
+ if (value < 0.95) evaluation++;
+ if (value < 0.90) evaluation++;
+ return evaluation;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
index 0e45ac1..7c8721c 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/HumanInteractionClassifier.java
@@ -69,13 +69,13 @@
mClassifierData = new ClassifierData(mDpi);
mHistoryEvaluator = new HistoryEvaluator();
- mStrokeClassifiers.add(new AnglesVarianceClassifier(mClassifierData));
+ mStrokeClassifiers.add(new AnglesClassifier(mClassifierData));
mStrokeClassifiers.add(new SpeedClassifier(mClassifierData));
mStrokeClassifiers.add(new DurationCountClassifier(mClassifierData));
mStrokeClassifiers.add(new EndPointRatioClassifier(mClassifierData));
mStrokeClassifiers.add(new EndPointLengthClassifier(mClassifierData));
mStrokeClassifiers.add(new AccelerationClassifier(mClassifierData));
- mStrokeClassifiers.add(new SpeedVarianceClassifier(mClassifierData));
+ mStrokeClassifiers.add(new SpeedAnglesClassifier(mClassifierData));
mStrokeClassifiers.add(new LengthCountClassifier(mClassifierData));
mGestureClassifiers.add(new PointerCountClassifier(mClassifierData));
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
index 1ea467b..cedf467 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountClassifier.java
@@ -17,8 +17,11 @@
package com.android.systemui.classifier;
/**
- * A classifier which looks at the ratio between the duration of the stroke and its number of
- * points.
+ * A classifier which looks at the ratio between the length of the stroke and its number of
+ * points. The number of points is subtracted by 2 because the UP event comes in with some delay
+ * and it should not influence the ratio and also strokes which are long and have a small number
+ * of points are punished more (these kind of strokes are usually bad ones and they tend to score
+ * well in other classifiers).
*/
public class LengthCountClassifier extends StrokeClassifier {
public LengthCountClassifier(ClassifierData classifierData) {
@@ -26,6 +29,7 @@
@Override
public float getFalseTouchEvaluation(int type, Stroke stroke) {
- return LengthCountEvaluator.evaluate(stroke.getTotalLength() / stroke.getCount());
+ return LengthCountEvaluator.evaluate(stroke.getTotalLength()
+ / Math.max(1.0f, stroke.getCount() - 2));
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java
index 68f163d1..dac7a6f 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/LengthCountEvaluator.java
@@ -23,10 +23,11 @@
public class LengthCountEvaluator {
public static float evaluate(float value) {
float evaluation = 0.0f;
- if (value < 0.07) evaluation++;
+ if (value < 0.09) evaluation++;
if (value < 0.05) evaluation++;
if (value < 0.02) evaluation++;
if (value > 0.6) evaluation++;
+ if (value > 0.9) evaluation++;
if (value > 1.2) evaluation++;
return evaluation;
}
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
similarity index 75%
rename from packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java
rename to packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
index 9a30fe1..d544a3d 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/SpeedVarianceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesClassifier.java
@@ -28,14 +28,17 @@
* A classifier which for each point from a stroke, it creates a point on plane with coordinates
* (timeOffsetNano, distanceCoveredUpToThisPoint) (scaled by DURATION_SCALE and LENGTH_SCALE)
* and then it calculates the angle variance of these points like the class
- * {@link AnglesVarianceClassifier} (without splitting it into two parts). The classifier ignores
+ * {@link AnglesClassifier} (without splitting it into two parts). The classifier ignores
* the last point of a stroke because the UP event comes in with some delay and this ruins the
- * smoothness of this curve
+ * smoothness of this curve. Additionally, the classifier classifies calculates the percentage of
+ * angles which value is in [PI - ANGLE_DEVIATION, 2* PI) interval. The reason why the classifier
+ * does that is because the speed of a good stroke is most often increases, so most of these angels
+ * should be in this interval.
*/
-public class SpeedVarianceClassifier extends StrokeClassifier {
+public class SpeedAnglesClassifier extends StrokeClassifier {
private HashMap<Stroke, Data> mStrokeMap = new HashMap<>();
- public SpeedVarianceClassifier(ClassifierData classifierData) {
+ public SpeedAnglesClassifier(ClassifierData classifierData) {
mClassifierData = classifierData;
}
@@ -64,12 +67,15 @@
@Override
public float getFalseTouchEvaluation(int type, Stroke stroke) {
- return SpeedVarianceEvaluator.evaluate(mStrokeMap.get(stroke).getAnglesVariance());
+ Data data = mStrokeMap.get(stroke);
+ return SpeedVarianceEvaluator.evaluate(data.getAnglesVariance())
+ + SpeedAnglesPercentageEvaluator.evaluate(data.getAnglesPercentage());
}
private static class Data {
private final float DURATION_SCALE = 1e8f;
private final float LENGTH_SCALE = 1.0f;
+ private final float ANGLE_DEVIATION = (float) Math.PI / 10.0f;
private List<Point> mLastThreePoints = new ArrayList<>();
private Point mPreviousPoint;
@@ -78,6 +84,8 @@
private float mSum;
private float mCount;
private float mDist;
+ private float mAnglesCount;
+ private float mAcceleratingAngles;
public Data() {
mPreviousPoint = null;
@@ -86,6 +94,7 @@
mSum = 0.0f;
mCount = 1.0f;
mDist = 0.0f;
+ mAnglesCount = mAcceleratingAngles = 0.0f;
}
public void addPoint(Point point) {
@@ -108,6 +117,11 @@
float angle = mLastThreePoints.get(1).getAngle(mLastThreePoints.get(0),
mLastThreePoints.get(2));
+ mAnglesCount++;
+ if (angle >= (float) Math.PI - ANGLE_DEVIATION) {
+ mAcceleratingAngles++;
+ }
+
float difference = angle - mPreviousAngle;
mSum += difference;
mSumSquares += difference * difference;
@@ -120,5 +134,12 @@
public float getAnglesVariance() {
return mSumSquares / mCount - (mSum / mCount) * (mSum / mCount);
}
+
+ public float getAnglesPercentage() {
+ if (mAnglesCount == 0.0f) {
+ return 1.0f;
+ }
+ return (mAcceleratingAngles) / mAnglesCount;
+ }
}
}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
new file mode 100644
index 0000000..2a45fa3
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/classifier/SpeedAnglesPercentageEvaluator.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 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.systemui.classifier;
+
+public class SpeedAnglesPercentageEvaluator {
+ public static float evaluate(float value) {
+ float evaluation = 0.0f;
+ if (value < 1.00) evaluation++;
+ if (value < 0.95) evaluation++;
+ if (value < 0.90) evaluation++;
+ return evaluation;
+ }
+}