blob: 02a65194885b4d8f010cd7ae44a31ad24aa32af8 [file] [log] [blame]
Yang Li35aa84b2009-05-18 18:29:05 -07001/*
2 * Copyright (C) 2008-2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Romain Guydb567c32009-05-21 16:23:21 -070017package android.gesture;
Yang Li35aa84b2009-05-18 18:29:05 -070018
Romain Guyb6d99b72009-05-21 15:05:50 -070019
Yang Li35aa84b2009-05-18 18:29:05 -070020/**
21 * An instance represents a sample if the label is available or a query if the
22 * label is null.
23 */
24class Instance {
Yang Li35aa84b2009-05-18 18:29:05 -070025 private static final int SEQUENCE_SAMPLE_SIZE = 16;
26
Yang Lie6ea0032009-05-21 14:47:59 -070027 private static final int PATCH_SAMPLE_SIZE = 16;
Yang Li35aa84b2009-05-18 18:29:05 -070028
29 private final static float[] ORIENTATIONS = {
Romain Guyf40f0742009-05-28 21:12:01 -070030 0, (float) (Math.PI / 4), (float) (Math.PI / 2), (float) (Math.PI * 3 / 4),
31 (float) Math.PI, -0, (float) (-Math.PI / 4), (float) (-Math.PI / 2),
32 (float) (-Math.PI * 3 / 4), (float) -Math.PI
Yang Li35aa84b2009-05-18 18:29:05 -070033 };
34
35 // the feature vector
36 final float[] vector;
37
38 // the label can be null
39 final String label;
40
Yang Li35aa84b2009-05-18 18:29:05 -070041 // the id of the instance
Romain Guyc5347272009-05-20 10:37:13 -070042 final long id;
Romain Guyf40f0742009-05-28 21:12:01 -070043
Yang Li35aa84b2009-05-18 18:29:05 -070044 private Instance(long id, float[] sample, String sampleName) {
Romain Guyc5347272009-05-20 10:37:13 -070045 this.id = id;
Yang Li35aa84b2009-05-18 18:29:05 -070046 vector = sample;
47 label = sampleName;
Yang Lie6ea0032009-05-21 14:47:59 -070048 }
Romain Guyf40f0742009-05-28 21:12:01 -070049
Yang Lie6ea0032009-05-21 14:47:59 -070050 private void normalize() {
51 float[] sample = vector;
Yang Li35aa84b2009-05-18 18:29:05 -070052 float sum = 0;
Romain Guyb6d99b72009-05-21 15:05:50 -070053
Yang Li35aa84b2009-05-18 18:29:05 -070054 int size = sample.length;
55 for (int i = 0; i < size; i++) {
56 sum += sample[i] * sample[i];
57 }
Romain Guyb6d99b72009-05-21 15:05:50 -070058
Romain Guyf40f0742009-05-28 21:12:01 -070059 float magnitude = (float)Math.sqrt(sum);
Yang Lie6ea0032009-05-21 14:47:59 -070060 for (int i = 0; i < size; i++) {
61 sample[i] /= magnitude;
62 }
Yang Li35aa84b2009-05-18 18:29:05 -070063 }
64
65 /**
66 * create a learning instance for a single stroke gesture
67 *
68 * @param gesture
69 * @param label
70 * @return the instance
71 */
Romain Guyf40f0742009-05-28 21:12:01 -070072 static Instance createInstance(int sequenceType, int orientationType, Gesture gesture, String label) {
Yang Li35aa84b2009-05-18 18:29:05 -070073 float[] pts;
Yang Lie6ea0032009-05-21 14:47:59 -070074 Instance instance;
Romain Guy0a637162009-05-29 14:43:54 -070075 if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) {
Romain Guyf40f0742009-05-28 21:12:01 -070076 pts = temporalSampler(orientationType, gesture);
Yang Lie6ea0032009-05-21 14:47:59 -070077 instance = new Instance(gesture.getID(), pts, label);
78 instance.normalize();
Yang Li35aa84b2009-05-18 18:29:05 -070079 } else {
80 pts = spatialSampler(gesture);
Yang Lie6ea0032009-05-21 14:47:59 -070081 instance = new Instance(gesture.getID(), pts, label);
Yang Li35aa84b2009-05-18 18:29:05 -070082 }
Yang Lie6ea0032009-05-21 14:47:59 -070083 return instance;
Yang Li35aa84b2009-05-18 18:29:05 -070084 }
Romain Guyf40f0742009-05-28 21:12:01 -070085
Yang Li35aa84b2009-05-18 18:29:05 -070086 private static float[] spatialSampler(Gesture gesture) {
Romain Guy46c53122010-02-04 14:19:50 -080087 return GestureUtils.spatialSampling(gesture, PATCH_SAMPLE_SIZE, false);
Yang Li35aa84b2009-05-18 18:29:05 -070088 }
89
Romain Guyf40f0742009-05-28 21:12:01 -070090 private static float[] temporalSampler(int orientationType, Gesture gesture) {
Romain Guy46c53122010-02-04 14:19:50 -080091 float[] pts = GestureUtils.temporalSampling(gesture.getStrokes().get(0),
Yang Li35aa84b2009-05-18 18:29:05 -070092 SEQUENCE_SAMPLE_SIZE);
Romain Guy46c53122010-02-04 14:19:50 -080093 float[] center = GestureUtils.computeCentroid(pts);
Romain Guyf40f0742009-05-28 21:12:01 -070094 float orientation = (float)Math.atan2(pts[1] - center[1], pts[0] - center[0]);
Yang Li35aa84b2009-05-18 18:29:05 -070095
96 float adjustment = -orientation;
Yang Li4758f122009-12-14 15:41:07 -080097 if (orientationType != GestureStore.ORIENTATION_INVARIANT) {
Yang Li35aa84b2009-05-18 18:29:05 -070098 int count = ORIENTATIONS.length;
99 for (int i = 0; i < count; i++) {
100 float delta = ORIENTATIONS[i] - orientation;
101 if (Math.abs(delta) < Math.abs(adjustment)) {
102 adjustment = delta;
103 }
104 }
105 }
106
Romain Guy46c53122010-02-04 14:19:50 -0800107 GestureUtils.translate(pts, -center[0], -center[1]);
108 GestureUtils.rotate(pts, adjustment);
Romain Guyb6d99b72009-05-21 15:05:50 -0700109
Yang Li35aa84b2009-05-18 18:29:05 -0700110 return pts;
111 }
112
113}