Loading core/java/android/gesture/GestureUtilities.java +65 −40 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ import static android.gesture.GestureConstants.*; final class GestureUtilities { private static final float SCALING_THRESHOLD = 0.26f; private static final float NONUNIFORM_SCALE = (float) Math.sqrt(2); private GestureUtilities() { } Loading @@ -46,63 +49,82 @@ final class GestureUtilities { } } static float[] spatialSampling(Gesture gesture, int sampleMatrixDimension) { static float[] spatialSampling(Gesture gesture, int sampleMatrixDimension, boolean uniformScaling) { final float targetPatchSize = sampleMatrixDimension - 1; // edge inclusive float[] sample = new float[sampleMatrixDimension * sampleMatrixDimension]; Arrays.fill(sample, 0); RectF rect = gesture.getBoundingBox(); float sx = targetPatchSize / rect.width(); float sy = targetPatchSize / rect.height(); final float gestureWidth = rect.width(); final float gestureHeight = rect.height(); float sx = targetPatchSize / gestureWidth; float sy = targetPatchSize / gestureHeight; if (uniformScaling) { float scale = sx < sy ? sx : sy; sx = scale; sy = scale; } else { float aspectRatio = gestureWidth / gestureHeight; if (aspectRatio > 1) { aspectRatio = 1 / aspectRatio; } if (aspectRatio < SCALING_THRESHOLD) { float scale = sx < sy ? sx : sy; sx = scale; sy = scale; } else { if (sx > sy) { float scale = sy * NONUNIFORM_SCALE; if (scale < sx) { sx = scale; } } else { float scale = sx * NONUNIFORM_SCALE; if (scale < sy) { sy = scale; } } } } float preDx = -rect.centerX(); float preDy = -rect.centerY(); float postDx = targetPatchSize / 2; float postDy = targetPatchSize / 2; final ArrayList<GestureStroke> strokes = gesture.getStrokes(); final int count = strokes.size(); int size; float xpos; float ypos; for (int index = 0; index < count; index++) { final GestureStroke stroke = strokes.get(index); float[] strokepoints = stroke.points; size = strokepoints.length; final float[] pts = new float[size]; for (int i = 0; i < size; i += 2) { pts[i] = (strokepoints[i] + preDx) * scale + postDx; pts[i + 1] = (strokepoints[i + 1] + preDy) * scale + postDy; pts[i] = (strokepoints[i] + preDx) * sx + postDx; pts[i + 1] = (strokepoints[i + 1] + preDy) * sy + postDy; } float segmentEndX = -1; float segmentEndY = -1; for (int i = 0; i < size; i += 2) { float segmentStartX = pts[i] < 0 ? 0 : pts[i]; float segmentStartY = pts[i + 1] < 0 ? 0 : pts[i + 1]; if (segmentStartX > targetPatchSize) { segmentStartX = targetPatchSize; } if (segmentStartY > targetPatchSize) { segmentStartY = targetPatchSize; } plot(segmentStartX, segmentStartY, sample, sampleMatrixDimension); if (segmentEndX != -1) { // evaluate horizontally if (segmentEndX > segmentStartX) { xpos = (float) Math.ceil(segmentStartX); float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); while (xpos < segmentEndX) { ypos = slope * (xpos - segmentStartX) + segmentStartY; plot(xpos, ypos, sample, sampleMatrixDimension); Loading @@ -110,18 +132,19 @@ final class GestureUtilities { } } else if (segmentEndX < segmentStartX){ xpos = (float) Math.ceil(segmentEndX); float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); while (xpos < segmentStartX) { ypos = slope * (xpos - segmentStartX) + segmentStartY; plot(xpos, ypos, sample, sampleMatrixDimension); xpos++; } } // evaluating vertically if (segmentEndY > segmentStartY) { ypos = (float) Math.ceil(segmentStartY); float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); while (ypos < segmentEndY) { xpos = invertSlope * (ypos - segmentStartY) + segmentStartX; plot(xpos, ypos, sample, sampleMatrixDimension); Loading @@ -129,7 +152,8 @@ final class GestureUtilities { } } else if (segmentEndY < segmentStartY) { ypos = (float) Math.ceil(segmentEndY); float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); while (ypos < segmentStartY) { xpos = invertSlope * (ypos - segmentStartY) + segmentStartX; plot(xpos, ypos, sample, sampleMatrixDimension); Loading @@ -137,13 +161,10 @@ final class GestureUtilities { } } } segmentEndX = segmentStartX; segmentEndY = segmentStartY; } } return sample; } Loading @@ -162,40 +183,44 @@ final class GestureUtilities { sample[index] = 1; } } else { double topLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yFloor - y, 2)); double topRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yFloor - y, 2)); double btmLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yCeiling - y, 2)); double btmRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yCeiling - y, 2)); double sum = topLeft + topRight + btmLeft + btmRight; double value = topLeft / sum; final double xFloorSq = Math.pow(xFloor - x, 2); final double yFloorSq = Math.pow(yFloor - y, 2); final double xCeilingSq = Math.pow(xCeiling - x, 2); final double yCeilingSq = Math.pow(yCeiling - y, 2); float topLeft = (float) Math.sqrt(xFloorSq + yFloorSq); float topRight = (float) Math.sqrt(xCeilingSq + yFloorSq); float btmLeft = (float) Math.sqrt(xFloorSq + yCeilingSq); float btmRight = (float) Math.sqrt(xCeilingSq + yCeilingSq); float sum = topLeft + topRight + btmLeft + btmRight; float value = topLeft / sum; int index = yFloor * sampleSize + xFloor; if (value > sample[index]){ sample[index] = (float) value; sample[index] = value; } value = topRight / sum; index = yFloor * sampleSize + xCeiling; if (value > sample[index]){ sample[index] = (float) value; sample[index] = value; } value = btmLeft / sum; index = yCeiling * sampleSize + xFloor; if (value > sample[index]){ sample[index] = (float) value; sample[index] = value; } value = btmRight / sum; index = yCeiling * sampleSize + xCeiling; if (value > sample[index]){ sample[index] = (float) value; sample[index] = value; } } } /** * Featurize a stroke into a vector of a given number of elements * Featurizes a stroke into a vector of a given number of elements * * @param stroke * @param sampleSize Loading core/java/android/gesture/Instance.java +1 −1 Original line number Diff line number Diff line Loading @@ -84,7 +84,7 @@ class Instance { } private static float[] spatialSampler(Gesture gesture) { return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE); return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE, false); } private static float[] temporalSampler(int orientationType, Gesture gesture) { Loading Loading
core/java/android/gesture/GestureUtilities.java +65 −40 Original line number Diff line number Diff line Loading @@ -28,6 +28,9 @@ import static android.gesture.GestureConstants.*; final class GestureUtilities { private static final float SCALING_THRESHOLD = 0.26f; private static final float NONUNIFORM_SCALE = (float) Math.sqrt(2); private GestureUtilities() { } Loading @@ -46,63 +49,82 @@ final class GestureUtilities { } } static float[] spatialSampling(Gesture gesture, int sampleMatrixDimension) { static float[] spatialSampling(Gesture gesture, int sampleMatrixDimension, boolean uniformScaling) { final float targetPatchSize = sampleMatrixDimension - 1; // edge inclusive float[] sample = new float[sampleMatrixDimension * sampleMatrixDimension]; Arrays.fill(sample, 0); RectF rect = gesture.getBoundingBox(); float sx = targetPatchSize / rect.width(); float sy = targetPatchSize / rect.height(); final float gestureWidth = rect.width(); final float gestureHeight = rect.height(); float sx = targetPatchSize / gestureWidth; float sy = targetPatchSize / gestureHeight; if (uniformScaling) { float scale = sx < sy ? sx : sy; sx = scale; sy = scale; } else { float aspectRatio = gestureWidth / gestureHeight; if (aspectRatio > 1) { aspectRatio = 1 / aspectRatio; } if (aspectRatio < SCALING_THRESHOLD) { float scale = sx < sy ? sx : sy; sx = scale; sy = scale; } else { if (sx > sy) { float scale = sy * NONUNIFORM_SCALE; if (scale < sx) { sx = scale; } } else { float scale = sx * NONUNIFORM_SCALE; if (scale < sy) { sy = scale; } } } } float preDx = -rect.centerX(); float preDy = -rect.centerY(); float postDx = targetPatchSize / 2; float postDy = targetPatchSize / 2; final ArrayList<GestureStroke> strokes = gesture.getStrokes(); final int count = strokes.size(); int size; float xpos; float ypos; for (int index = 0; index < count; index++) { final GestureStroke stroke = strokes.get(index); float[] strokepoints = stroke.points; size = strokepoints.length; final float[] pts = new float[size]; for (int i = 0; i < size; i += 2) { pts[i] = (strokepoints[i] + preDx) * scale + postDx; pts[i + 1] = (strokepoints[i + 1] + preDy) * scale + postDy; pts[i] = (strokepoints[i] + preDx) * sx + postDx; pts[i + 1] = (strokepoints[i + 1] + preDy) * sy + postDy; } float segmentEndX = -1; float segmentEndY = -1; for (int i = 0; i < size; i += 2) { float segmentStartX = pts[i] < 0 ? 0 : pts[i]; float segmentStartY = pts[i + 1] < 0 ? 0 : pts[i + 1]; if (segmentStartX > targetPatchSize) { segmentStartX = targetPatchSize; } if (segmentStartY > targetPatchSize) { segmentStartY = targetPatchSize; } plot(segmentStartX, segmentStartY, sample, sampleMatrixDimension); if (segmentEndX != -1) { // evaluate horizontally if (segmentEndX > segmentStartX) { xpos = (float) Math.ceil(segmentStartX); float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); while (xpos < segmentEndX) { ypos = slope * (xpos - segmentStartX) + segmentStartY; plot(xpos, ypos, sample, sampleMatrixDimension); Loading @@ -110,18 +132,19 @@ final class GestureUtilities { } } else if (segmentEndX < segmentStartX){ xpos = (float) Math.ceil(segmentEndX); float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); float slope = (segmentEndY - segmentStartY) / (segmentEndX - segmentStartX); while (xpos < segmentStartX) { ypos = slope * (xpos - segmentStartX) + segmentStartY; plot(xpos, ypos, sample, sampleMatrixDimension); xpos++; } } // evaluating vertically if (segmentEndY > segmentStartY) { ypos = (float) Math.ceil(segmentStartY); float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); while (ypos < segmentEndY) { xpos = invertSlope * (ypos - segmentStartY) + segmentStartX; plot(xpos, ypos, sample, sampleMatrixDimension); Loading @@ -129,7 +152,8 @@ final class GestureUtilities { } } else if (segmentEndY < segmentStartY) { ypos = (float) Math.ceil(segmentEndY); float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); float invertSlope = (segmentEndX - segmentStartX) / (segmentEndY - segmentStartY); while (ypos < segmentStartY) { xpos = invertSlope * (ypos - segmentStartY) + segmentStartX; plot(xpos, ypos, sample, sampleMatrixDimension); Loading @@ -137,13 +161,10 @@ final class GestureUtilities { } } } segmentEndX = segmentStartX; segmentEndY = segmentStartY; } } return sample; } Loading @@ -162,40 +183,44 @@ final class GestureUtilities { sample[index] = 1; } } else { double topLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yFloor - y, 2)); double topRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yFloor - y, 2)); double btmLeft = Math.sqrt(Math.pow(xFloor - x, 2) + Math.pow(yCeiling - y, 2)); double btmRight = Math.sqrt(Math.pow(xCeiling - x, 2) + Math.pow(yCeiling - y, 2)); double sum = topLeft + topRight + btmLeft + btmRight; double value = topLeft / sum; final double xFloorSq = Math.pow(xFloor - x, 2); final double yFloorSq = Math.pow(yFloor - y, 2); final double xCeilingSq = Math.pow(xCeiling - x, 2); final double yCeilingSq = Math.pow(yCeiling - y, 2); float topLeft = (float) Math.sqrt(xFloorSq + yFloorSq); float topRight = (float) Math.sqrt(xCeilingSq + yFloorSq); float btmLeft = (float) Math.sqrt(xFloorSq + yCeilingSq); float btmRight = (float) Math.sqrt(xCeilingSq + yCeilingSq); float sum = topLeft + topRight + btmLeft + btmRight; float value = topLeft / sum; int index = yFloor * sampleSize + xFloor; if (value > sample[index]){ sample[index] = (float) value; sample[index] = value; } value = topRight / sum; index = yFloor * sampleSize + xCeiling; if (value > sample[index]){ sample[index] = (float) value; sample[index] = value; } value = btmLeft / sum; index = yCeiling * sampleSize + xFloor; if (value > sample[index]){ sample[index] = (float) value; sample[index] = value; } value = btmRight / sum; index = yCeiling * sampleSize + xCeiling; if (value > sample[index]){ sample[index] = (float) value; sample[index] = value; } } } /** * Featurize a stroke into a vector of a given number of elements * Featurizes a stroke into a vector of a given number of elements * * @param stroke * @param sampleSize Loading
core/java/android/gesture/Instance.java +1 −1 Original line number Diff line number Diff line Loading @@ -84,7 +84,7 @@ class Instance { } private static float[] spatialSampler(Gesture gesture) { return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE); return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE, false); } private static float[] temporalSampler(int orientationType, Gesture gesture) { Loading