GestureHandler.java

00001 package edu.stanford.hci.r3.events.handlers;
00002 
00003 import edu.stanford.hci.r3.events.EventHandler;
00004 import edu.stanford.hci.r3.events.PenEvent;
00005 import edu.stanford.hci.r3.units.Units;
00006 import edu.stanford.hci.r3.units.coordinates.PercentageCoordinates;
00007 
00019 public abstract class GestureHandler extends EventHandler {
00020 
00026         public static enum GestureDirection {
00027                 E, // 0 radians (cone from -PI/8 to PI/8)
00028                 N, // PI/2
00029                 NE, // PI/4
00030                 NW, // 3PI/4
00031                 S, // -PI/2
00032                 SE, // -PI/4
00033                 SW, // -3PI/4
00034                 W
00035                 // +/- PI (cone from -7PI/8 ... to -PI and from 7PI/8 to PI)
00036         }
00037 
00038         private double dx;
00039 
00040         private double dy;
00041 
00042         private Units firstPercentageX;
00043 
00044         private Units firstPercentageY;
00045 
00050         private int gestureThreshold = 4;
00051 
00052         private Units lastPercentageX;
00053 
00054         private Units lastPercentageY;
00055 
00056         private int numSamples;
00057 
00061         public void handleEvent(PenEvent event) {
00062                 PercentageCoordinates percentageLocation = event.getPercentageLocation();
00063                 if (event.isTypePenDown()) {
00064                         firstPercentageX = percentageLocation.getActualValueInXDirection();
00065                         firstPercentageY = percentageLocation.getActualValueInYDirection();
00066                         numSamples = 0;
00067                 } else if (event.isTypePenUp()) {
00068                         // register a gesture on pen up
00069                         // only if we get more than N samples do we register a gesture
00070                         if (numSamples > gestureThreshold) {
00071                                 dx = lastPercentageX.getValue() - firstPercentageX.getValue();
00072                                 dy = lastPercentageY.getValue() - firstPercentageY.getValue();
00073 
00074                                 // calculate the angle, and decide the compass direction
00075                                 double theta = Math.atan2(dy, dx);
00076 
00077                                 // makes it easier to binary search
00078                                 // we negate it because our y actually grows going DOWN the page.
00079                                 // This is opposite from the standard cartesian coordinate system.
00080                                 double testTheta = -theta + Math.PI / 8;
00081 
00082                                 final double PI_4 = Math.PI / 4;
00083                                 final double PI_2 = Math.PI / 2;
00084                                 final double THREE_PI_4 = 3 * Math.PI / 4;
00085 
00086                                 // Do a ~binary search! =)
00087                                 if (testTheta > 0) { // E, NE, N, NW, W
00088                                         if (testTheta < PI_2) { // NE or E
00089                                                 if (testTheta < PI_4) { // E
00090                                                         handleMark(event, GestureDirection.E);
00091                                                 } else { // NE
00092                                                         handleMark(event, GestureDirection.NE);
00093                                                 }
00094                                         } else { // N, NW, W... anything greater than PI/2
00095                                                 if (testTheta < THREE_PI_4) { // N
00096                                                         handleMark(event, GestureDirection.N);
00097                                                 } else if (testTheta < Math.PI) { // NW
00098                                                         handleMark(event, GestureDirection.NW);
00099                                                 } else { // W
00100                                                         handleMark(event, GestureDirection.W);
00101                                                 }
00102                                         }
00103                                 } else { // SE, S, SW, W
00104                                         if (testTheta > -PI_2) { // S, SE
00105                                                 if (testTheta > -PI_4) {
00106                                                         handleMark(event, GestureDirection.SE);
00107                                                 } else {
00108                                                         handleMark(event, GestureDirection.S);
00109                                                 }
00110                                         } else { // SW, W
00111                                                 if (testTheta > -THREE_PI_4) {
00112                                                         handleMark(event, GestureDirection.SW);
00113                                                 } else {
00114                                                         handleMark(event, GestureDirection.W);
00115                                                 }
00116                                         }
00117 
00118                                 }
00119 
00120                         }
00121                 } else {
00122                         numSamples++;
00123                         lastPercentageX = percentageLocation.getActualValueInXDirection();
00124                         lastPercentageY = percentageLocation.getActualValueInYDirection();
00125                 }
00126         }
00127 
00132         public abstract void handleMark(PenEvent e, GestureDirection dir);
00133 
00134         /*
00135          * (non-Javadoc)
00136          * 
00137          * @see edu.stanford.hci.r3.events.EventHandler#toString()
00138          */
00139         public String toString() {
00140                 return "GestureHandler";
00141         }
00142 }

Generated on Sat Apr 14 18:21:35 2007 for R3 Paper Toolkit by  doxygen 1.4.7