Home | History | Annotate | Download | only in gesture
      1 /*
      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 
     17 package android.gesture;
     18 
     19 
     20 /**
     21  * An instance represents a sample if the label is available or a query if the
     22  * label is null.
     23  */
     24 class Instance {
     25     private static final int SEQUENCE_SAMPLE_SIZE = 16;
     26 
     27     private static final int PATCH_SAMPLE_SIZE = 16;
     28 
     29     private final static float[] ORIENTATIONS = {
     30             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
     33     };
     34 
     35     // the feature vector
     36     final float[] vector;
     37 
     38     // the label can be null
     39     final String label;
     40 
     41     // the id of the instance
     42     final long id;
     43 
     44     private Instance(long id, float[] sample, String sampleName) {
     45         this.id = id;
     46         vector = sample;
     47         label = sampleName;
     48     }
     49 
     50     private void normalize() {
     51         float[] sample = vector;
     52         float sum = 0;
     53 
     54         int size = sample.length;
     55         for (int i = 0; i < size; i++) {
     56             sum += sample[i] * sample[i];
     57         }
     58 
     59         float magnitude = (float)Math.sqrt(sum);
     60         for (int i = 0; i < size; i++) {
     61             sample[i] /= magnitude;
     62         }
     63     }
     64 
     65     /**
     66      * create a learning instance for a single stroke gesture
     67      *
     68      * @param gesture
     69      * @param label
     70      * @return the instance
     71      */
     72     static Instance createInstance(int sequenceType, int orientationType, Gesture gesture, String label) {
     73         float[] pts;
     74         Instance instance;
     75         if (sequenceType == GestureStore.SEQUENCE_SENSITIVE) {
     76             pts = temporalSampler(orientationType, gesture);
     77             instance = new Instance(gesture.getID(), pts, label);
     78             instance.normalize();
     79         } else {
     80             pts = spatialSampler(gesture);
     81             instance = new Instance(gesture.getID(), pts, label);
     82         }
     83         return instance;
     84     }
     85 
     86     private static float[] spatialSampler(Gesture gesture) {
     87         return GestureUtils.spatialSampling(gesture, PATCH_SAMPLE_SIZE, false);
     88     }
     89 
     90     private static float[] temporalSampler(int orientationType, Gesture gesture) {
     91         float[] pts = GestureUtils.temporalSampling(gesture.getStrokes().get(0),
     92                 SEQUENCE_SAMPLE_SIZE);
     93         float[] center = GestureUtils.computeCentroid(pts);
     94         float orientation = (float)Math.atan2(pts[1] - center[1], pts[0] - center[0]);
     95 
     96         float adjustment = -orientation;
     97         if (orientationType != GestureStore.ORIENTATION_INVARIANT) {
     98             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 
    107         GestureUtils.translate(pts, -center[0], -center[1]);
    108         GestureUtils.rotate(pts, adjustment);
    109 
    110         return pts;
    111     }
    112 
    113 }
    114