114 lines
3.5 KiB
Java
Executable File
114 lines
3.5 KiB
Java
Executable File
/*
|
|
* Copyright (C) 2008-2009 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 android.gesture;
|
|
|
|
|
|
/**
|
|
* An instance represents a sample if the label is available or a query if the
|
|
* label is null.
|
|
*/
|
|
class Instance {
|
|
private static final int SEQUENCE_SAMPLE_SIZE = 16;
|
|
|
|
private static final int PATCH_SAMPLE_SIZE = 16;
|
|
|
|
private final static float[] ORIENTATIONS = {
|
|
0, (float) (Math.PI / 4), (float) (Math.PI / 2), (float) (Math.PI * 3 / 4),
|
|
(float) Math.PI, -0, (float) (-Math.PI / 4), (float) (-Math.PI / 2),
|
|
(float) (-Math.PI * 3 / 4), (float) -Math.PI
|
|
};
|
|
|
|
// the feature vector
|
|
final float[] vector;
|
|
|
|
// the label can be null
|
|
final String label;
|
|
|
|
// the id of the instance
|
|
final long id;
|
|
|
|
private Instance(long id, float[] sample, String sampleName) {
|
|
this.id = id;
|
|
vector = sample;
|
|
label = sampleName;
|
|
}
|
|
|
|
private void normalize() {
|
|
float[] sample = vector;
|
|
float sum = 0;
|
|
|
|
int size = sample.length;
|
|
for (int i = 0; i < size; i++) {
|
|
sum += sample[i] * sample[i];
|
|
}
|
|
|
|
float magnitude = (float)Math.sqrt(sum);
|
|
for (int i = 0; i < size; i++) {
|
|
sample[i] /= magnitude;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* create a learning instance for a single stroke gesture
|
|
*
|
|
* @param gesture
|
|
* @param label
|
|
* @return the instance
|
|
*/
|
|
static Instance createInstance(int sequenceType, int orientationType, Gesture gesture, String label) {
|
|
float[] pts;
|
|
Instance instance;
|
|
if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) {
|
|
pts = temporalSampler(orientationType, gesture);
|
|
instance = new Instance(gesture.getID(), pts, label);
|
|
instance.normalize();
|
|
} else {
|
|
pts = spatialSampler(gesture);
|
|
instance = new Instance(gesture.getID(), pts, label);
|
|
}
|
|
return instance;
|
|
}
|
|
|
|
private static float[] spatialSampler(Gesture gesture) {
|
|
return GestureUtils.spatialSampling(gesture, PATCH_SAMPLE_SIZE, false);
|
|
}
|
|
|
|
private static float[] temporalSampler(int orientationType, Gesture gesture) {
|
|
float[] pts = GestureUtils.temporalSampling(gesture.getStrokes().get(0),
|
|
SEQUENCE_SAMPLE_SIZE);
|
|
float[] center = GestureUtils.computeCentroid(pts);
|
|
float orientation = (float)Math.atan2(pts[1] - center[1], pts[0] - center[0]);
|
|
|
|
float adjustment = -orientation;
|
|
if (orientationType != GestureStore.ORIENTATION_INVARIANT) {
|
|
int count = ORIENTATIONS.length;
|
|
for (int i = 0; i < count; i++) {
|
|
float delta = ORIENTATIONS[i] - orientation;
|
|
if (Math.abs(delta) < Math.abs(adjustment)) {
|
|
adjustment = delta;
|
|
}
|
|
}
|
|
}
|
|
|
|
GestureUtils.translate(pts, -center[0], -center[1]);
|
|
GestureUtils.rotate(pts, adjustment);
|
|
|
|
return pts;
|
|
}
|
|
|
|
}
|