View Javadoc

1   /*
2    * @(#)$Id: GestureTool.java 796 2010-05-04 14:54:35Z bpuype $
3    *
4    * Author       :   Ueli Kurmann, igesture@uelikurmann.ch
5    *
6    * Purpose      :   Collection of commonly used static methods.
7    *
8    * -----------------------------------------------------------------------
9    *
10   * Revision Information:
11   *
12   * Date             Who         Reason
13   *
14   * Dec 26, 2006     ukurmann    Initial Release
15   * Mar 22, 2007     bsigner     Cleanup
16   *
17   * -----------------------------------------------------------------------
18   *
19   * Copyright 1999-2009 ETH Zurich. All Rights Reserved.
20   *
21   * This software is the proprietary information of ETH Zurich.
22   * Use is subject to license terms.
23   * 
24   */
25  
26  
27  package org.ximtec.igesture.util;
28  
29  import java.awt.Color;
30  import java.awt.Graphics;
31  import java.awt.geom.Rectangle2D;
32  import java.awt.image.BufferedImage;
33  import java.util.ArrayList;
34  import java.util.HashMap;
35  import java.util.HashSet;
36  import java.util.List;
37  import java.util.Set;
38  
39  import org.sigtec.ink.Note;
40  import org.sigtec.ink.Point;
41  import org.sigtec.ink.Trace;
42  import org.sigtec.ink.TraceTool;
43  import org.ximtec.igesture.core.Gesture;
44  import org.ximtec.igesture.core.GestureClass;
45  import org.ximtec.igesture.core.GestureSample;
46  import org.ximtec.igesture.core.GestureSet;
47  import org.ximtec.igesture.core.SampleDescriptor;
48  import org.ximtec.igesture.core.TestSet;
49  import org.ximtec.igesture.core.composite.Constraint;
50  import org.ximtec.igesture.util.additions3d.RecordedGesture3D;
51  
52  
53  /**
54   * Collection of commonly used static methods.
55   * 
56   * @version 1.0, Dec 2006
57   * @author Ueli Kurmann, igesture@uelikurmann.ch
58   * @author Beat Signer, signer@inf.ethz.ch
59   */
60  public class GestureTool {
61  
62     private static final String COMBINED_SET = "CombinedGestureSet";
63     private static final String DEFAULT_NAME = "Name";
64  
65  
66     public static double scaleTraceTo(org.sigtec.ink.Trace trace,
67           double maxWidth, double maxHeight) {
68        Rectangle2D bounds = trace.getBounds2D();
69        double width = bounds.getWidth();
70        double height = bounds.getHeight();
71        double scaleX = maxWidth / width;
72        double scaleY = maxHeight / height;
73        return (scaleX < scaleY) ? scaleX : scaleY;
74     } // scaleTraceTo
75  
76  
77     /**
78      * Combines a list of gesture set to one gesture set.
79      * 
80      * @param sets the list of gesture sets to be combined.
81      * @return the combined gesture set.
82      */
83     public static GestureSet combine(List<GestureSet> sets) {
84        final Set<GestureClass> gestureClasses = new HashSet<GestureClass>();
85        
86        for (GestureSet set : sets) {
87           gestureClasses.addAll(set.getGestureClasses());
88        }
89        
90        return new GestureSet(new ArrayList<GestureClass>(gestureClasses));
91     } // combine
92  
93  
94     /**
95      * Detects characteristic points of a trace. A point is characteristic if it
96      * is involved in a significant change of direction.
97      * 
98      * @param trace the trace to be filtered.
99      * @param minAngle the minimal angle between two sequences.
100     * @param minDistance the minimal distance between two points.
101     * @return the filtered trace.
102     */
103    public static Trace getCharacteristicTrace(Trace trace, double minAngle,
104          double minDistance) {
105       Trace inputTrace = TraceTool.filterTrace(trace, minDistance);
106       Trace resultTrace = new Trace();
107 
108       if (inputTrace.size() > 2) {
109          Point p1 = trace.get(0);
110          Point p2 = trace.get(2);
111          Point p3 = null;
112          double angle1 = getAngle(p1, p2);
113          double angle2 = 0;
114          // add the first point to the result
115          resultTrace.add(p1);
116 
117          for (int i = 2; i < inputTrace.size(); i++) {
118             p3 = inputTrace.get(i);
119             angle2 = getAngle(p2, p3);
120 
121             if (Math.abs(angle1 - angle2) > minAngle) {
122                // p2 is significant and part of the result
123                resultTrace.add(p2);
124                // go to the next section
125                p1 = p2;
126                p2 = p3;
127             }
128             else {
129                // section p1-p3 is combined , p2 is not significant and can
130                // be
131                // removed
132                p2 = p3;
133             }
134 
135             angle1 = getAngle(p1, p2);
136          }
137 
138          // add the end point of the input trace
139          resultTrace.add(inputTrace.get(inputTrace.size() - 1));
140       }
141       else {
142          resultTrace = inputTrace;
143       }
144 
145       return resultTrace;
146    } // getCharacteristicTrace
147 
148 
149    /**
150     * Creates a characteristic note.
151     * @param note the note to be filtered.
152     * @param minAngle the minimal angle between two sequences.
153     * @param minDistance the minimal distance between two points.
154     * @return the filtered note.
155     */
156    public static Note getCharacteristicNote(Note note, double minAngle,
157          double minDistance) {
158       Note result = new Note();
159 
160       for (Trace trace : note.getTraces()) {
161          result.add(getCharacteristicTrace(trace, minAngle, minDistance));
162       }
163 
164       return result;
165    } // getCharacteristicNote
166 
167 
168    /**
169     * Computes the angle between two points.
170     * 
171     * @param p1 the first point.
172     * @param p2 the second point.
173     * @return the angle between p1 and p2.
174     */
175    public static double getAngle(Point p1, Point p2) {
176       double r = p1.distance(p2);
177       double x = p2.getX() - p1.getX();
178       double alpha = Math.toDegrees(Math.acos(x / r));
179 
180       if (p2.getY() - p1.getY() < 0) {
181          alpha = 360 - alpha;
182       }
183 
184       return alpha;
185    } // getAngle
186 
187 
188    /**
189     * Creates an image from the note.
190     * @param n the note for which an image has to be created.
191     * @param width the width of the image.
192     * @param height the height of the image.
193     * @return the buffered image.
194     */
195    public static BufferedImage createNoteImage(Note n, int width, int height) {
196       Note note = (Note)n.clone();
197       BufferedImage bufferedImage = new BufferedImage(width, height,
198             BufferedImage.TYPE_INT_ARGB);
199       Graphics graphic = bufferedImage.getGraphics();
200       graphic.setColor(Color.BLACK);
201       note.scaleTo(width - 10, height - 10);
202       note.moveTo(5, 5);
203       note.paint(graphic);
204       return bufferedImage;
205    } // createNoteImage
206    
207    
208    /**
209     * Creates an image from the recordedgesture3d
210     * @param gesture the recordedgesture3d for which an image has to be created.
211     * @param width the width of the image.
212     * @param height the height of the image.
213     * @return the buffered image.
214     */
215    public static BufferedImage createRecordedGesture3DImage(RecordedGesture3D gesture, int width, int height) {
216    		RecordedGesture3D record = (RecordedGesture3D)gesture.clone();
217    		BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
218    		Graphics graphic = bufferedImage.getGraphics();
219    		RecordedGesture3DTool.paintGesture(record,graphic, width, height, false);
220    		return bufferedImage;
221    } //createRecordeGesture3DImage
222 
223 
224 
225 	/**
226 	 * Creates an image from the constraint
227 	 * @param constraint the constraint for which an image has to be created.
228 	 * @param width the width of the image.
229      * @param height the height of the image.
230      * @return the buffered image
231 	 */
232 	public static BufferedImage createCompositeImage(Constraint constraint, int width, int height) {
233 		String name = constraint.getClass().getSimpleName();
234 		int index = name.indexOf("Constraint");
235 		BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
236 		Graphics graphic = bufferedImage.getGraphics();
237 		graphic.setColor(Color.BLACK);
238 		graphic.drawString(name.substring(0, index), 5, height/2-5);
239 		graphic.drawString("Constraint",5,height/2+5);
240 		return bufferedImage;
241 	}
242 
243    /**
244     * Combines samples (SampleDescriptor) from different gesture sets.
245     * @param sets a list of gesture sets.
246     * @return samples from different gesture sets.
247     */
248    public static GestureSet combineSampleData(List<GestureSet> sets) {
249       HashMap<String, GestureClass> samples = new HashMap<String, GestureClass>();
250       GestureSet result = new GestureSet(COMBINED_SET);
251 
252       for (GestureSet set : sets) {
253 
254          for (GestureClass gestureClass : set.getGestureClasses()) {
255 
256             if (samples.containsKey(gestureClass.getName())) {
257                GestureClass target = samples.get(gestureClass.getName());
258 
259                for (Gesture<Note> sample : gestureClass.getDescriptor(
260                      SampleDescriptor.class).getSamples()) {
261                   target.getDescriptor(SampleDescriptor.class).addSample(sample);
262                }
263 
264             }
265             else {
266                samples.put(gestureClass.getName(), gestureClass);
267                result.addGestureClass(gestureClass);
268             }
269 
270          }
271 
272       }
273       return result;
274    } // combineSampleData
275 
276 
277    /**
278     * Transforms a gesture set into a test set.
279     * @param set the gesture set to be transformed.
280     * @return the test set.
281     */
282    public static TestSet createTestSet(GestureSet set) {
283       TestSet testSet = new TestSet(DEFAULT_NAME);
284 
285       for (GestureClass gestureClass : set.getGestureClasses()) {
286 
287          for (Gesture<?> sample : gestureClass.getDescriptor(
288                SampleDescriptor.class).getSamples()) {
289             testSet.add(new GestureSample(sample.getSource(),gestureClass.getName(), (Note)sample
290                   .getGesture()));
291          }
292 
293       }
294 
295       return testSet;
296    } // createTestSet
297 
298 
299    /**
300     * Creates a noise test set from the gesture set.
301     * @param set the gesture set.
302     * @return a noise test set.
303     */
304    public static TestSet createNoise(GestureSet set) {
305       TestSet testSet = new TestSet(DEFAULT_NAME);
306 
307       for (GestureClass gestureClass : set.getGestureClasses()) {
308 
309          for (Gesture<?> sample : gestureClass.getDescriptor(
310                SampleDescriptor.class).getSamples()) {
311             testSet.add(new GestureSample(sample.getSource(),TestSet.NOISE, (Note)sample.getGesture()));
312          }
313 
314       }
315 
316       return testSet;
317    } // createNoise
318 
319 
320    /**
321     * Combines different test sets.
322     * @param testSets the test sets to be combined.
323     * @return the combined test sets.
324     */
325    public static TestSet combineTestSet(TestSet[] testSets) {
326       TestSet result = new TestSet(DEFAULT_NAME);
327 
328       for (TestSet set : testSets) {
329          result.addTestClasses(set.getTestClasses());
330       }
331 
332       return result;
333    } // combineTestSet
334    
335    
336    public static void hasSampleEnoughPoints(GestureSet set, int min){
337       for(GestureClass gestureClass:set.getGestureClasses()){
338          hasSampleEnoughPoints(gestureClass, min);
339       }
340    } 
341    
342    public static void hasSampleEnoughPoints(GestureClass gestureClass, int min){
343       if(gestureClass.hasDescriptor(SampleDescriptor.class)){
344          SampleDescriptor descriptor = gestureClass.getDescriptor(SampleDescriptor.class);
345          for(Gesture<?> sample:descriptor.getSamples()){
346             if(((Note)sample.getGesture()).getPoints().size() <= min){
347                System.out.println(gestureClass.getName()+"  :  "+ ((Note)sample.getGesture()).getPoints().size());
348             }
349          }
350       }
351    }
352 
353 }