1
2
3
4 package org.ximtec.igesture.util;
5
6 import java.awt.Color;
7 import java.awt.Font;
8 import java.awt.Graphics;
9 import java.awt.Graphics2D;
10 import java.awt.Point;
11 import java.awt.Rectangle;
12 import java.awt.RenderingHints;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16 import java.util.Vector;
17
18 import org.sigtec.ink.Note;
19 import org.sigtec.ink.Trace;
20 import org.ximtec.igesture.util.additions3d.AccelerationSample;
21 import org.ximtec.igesture.util.additions3d.Accelerations;
22 import org.ximtec.igesture.util.additions3d.RecordedGesture3D;
23 import org.ximtec.igesture.core.Gesture;
24 import org.ximtec.igesture.core.GestureSample;
25 import org.ximtec.igesture.util.additions3d.Point3D;
26
27
28
29
30
31 public class RecordedGesture3DTool {
32
33 public static void paintGesture(RecordedGesture3D gs, Graphics g, int width, int height, boolean drawFieldTitles)
34 {
35 List<Rectangle> fields = paintStructure(g,width,height, drawFieldTitles);
36
37 ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
38 RenderingHints.VALUE_ANTIALIAS_ON);
39
40 Accelerations acc = gs.getAccelerations();
41
42
43 List<Gesture<Note>> notes = splitToPlanes(gs);
44
45
46 List<Trace> traces = new Vector<Trace>();
47 for (int i = 0; i < notes.size(); i++) {
48 traces.add(notes.get(i).getGesture().get(0));
49 }
50 traces = scaleTraces(traces, 10, fields.subList(0, 3));
51 notes.clear();
52 for (int i = 0; i < traces.size(); i++) {
53 Note note = new Note();
54 note.add(traces.get(i));
55 Gesture<Note> gesture = new GestureSample("", note);
56 notes.add(gesture);
57 }
58
59
60 Gesture<Note> gest = notes.get(0);
61 Note noteXY = gest.getGesture();
62 gest = notes.get(1);
63 Note noteYZ = gest.getGesture();
64 gest = notes.get(2);
65 Note noteZX = gest.getGesture();
66
67
68 drawPlane(noteXY, fields.get(0), g);
69 drawPlane(noteYZ, fields.get(1), g);
70 drawPlane(noteZX, fields.get(2), g);
71
72 drawAccelerationsGraph(acc, fields.get(3), 0.02, g);
73
74 if(drawFieldTitles)
75 g.drawString(""+gs.size(), width/2-5, height/2+5);
76
77 ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
78 RenderingHints.VALUE_ANTIALIAS_OFF);
79 }
80
81
82
83
84 public static List<Rectangle> paintStructure(Graphics g, int width, int height, boolean drawFieldTitles)
85 {
86 g.setColor(Color.WHITE);
87 g.fillRect(0, 0, width, height);
88 g.setColor(Color.BLACK);
89
90
91 List<Rectangle> fields = calculateFieldSizes(0.02,width,height);
92 Rectangle XYfield = fields.get(0);
93 Rectangle YZfield = fields.get(1);
94 Rectangle ZXfield = fields.get(2);
95 Rectangle graphField = fields.get(3);
96
97 g.drawRect((int) XYfield.getX(), (int) XYfield.getY(), (int) XYfield.getWidth(), (int) XYfield.getHeight());
98 g.drawRect((int) YZfield.getX(), (int) YZfield.getY(), (int) YZfield.getWidth(), (int) YZfield.getHeight());
99 g.drawRect((int) ZXfield.getX(), (int) ZXfield.getY(), (int) ZXfield.getWidth(), (int) ZXfield.getHeight());
100 g.drawRect((int) graphField.getX(), (int) graphField.getY(), (int) graphField.getWidth(), (int) graphField.getHeight());
101 if(drawFieldTitles)
102 {
103 ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
104 RenderingHints.VALUE_ANTIALIAS_ON);
105
106
107 g.setColor(Color.RED);
108 g.drawString("XY-Plane", (int) (XYfield.getX() + 10),(int) (XYfield.getY() + 15));
109 g.drawString("YZ-Plane", (int) (YZfield.getX() + 10),(int) (YZfield.getY() + 15));
110 g.drawString("ZX-Plane", (int) (ZXfield.getX() + 10),(int) (ZXfield.getY() + 15));
111 g.drawString("Accelerations", (int) (graphField.getX() + 10),(int) (graphField.getY() + 15));
112
113
114 ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING,
115 RenderingHints.VALUE_ANTIALIAS_OFF);
116 }
117 return fields;
118 }
119
120
121
122
123
124
125
126
127
128
129 private static List<Rectangle> calculateFieldSizes(double spacePercentage, int width, int height) {
130
131 int spacerHorizontal = (int) (spacePercentage * width);
132 int spacerVertical = (int) (spacePercentage * height);
133
134 int fieldWidth = (int) ((width - (4 * spacerHorizontal)) * 0.5);
135 int fieldHeight = (int) ((height - (4 * spacerVertical)) * 0.5);
136
137 Rectangle field1 = new Rectangle(spacerHorizontal, spacerVertical,
138 fieldWidth, fieldHeight);
139 Rectangle field2 = new Rectangle((spacerHorizontal * 3) + fieldWidth,
140 spacerVertical, fieldWidth, fieldHeight);
141 Rectangle field3 = new Rectangle(spacerHorizontal, (spacerVertical * 3)
142 + fieldHeight, fieldWidth, fieldHeight);
143 Rectangle field4 = new Rectangle((spacerHorizontal * 3) + fieldWidth,
144 (spacerVertical * 3) + fieldHeight, fieldWidth, fieldHeight);
145
146 List<Rectangle> fields = new Vector<Rectangle>();
147 fields.add(field1);
148 fields.add(field2);
149 fields.add(field3);
150 fields.add(field4);
151
152 return fields;
153 }
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169 private static void drawAccelerationsGraph(Accelerations acc, Rectangle field,
170 double spacePercentage, Graphics g) {
171 g.setColor(Color.BLACK);
172
173 if (acc != null) {
174
175
176 int margin = (int) (spacePercentage * field.getWidth());
177
178
179 Rectangle fieldX = new Rectangle((int) field.getX() + margin,
180 (int) field.getY() + margin, (int) field.getWidth()
181 - (2 * margin), (int) (field.getHeight() / 3)
182 - (2 * margin));
183 Rectangle fieldY = new Rectangle((int) field.getX() + margin,
184 (int) (field.getY() + field.getHeight() / 3) + margin,
185 (int) field.getWidth() - (2 * margin), (int) (field
186 .getHeight() / 3)
187 - (2 * margin));
188 Rectangle fieldZ = new Rectangle((int) field.getX() + margin,
189 (int) (field.getY() + field.getHeight() * 0.67) + margin,
190 (int) field.getWidth() - (2 * margin), (int) (field
191 .getHeight() / 3)
192 - (2 * margin));
193
194
195 List<List<Point>> buffers = scaleAccelerations(acc, fieldX);
196
197
198 drawGraph(buffers.get(0), fieldX, Color.GRAY, Color.RED, "X",
199 g);
200 drawGraph(buffers.get(1), fieldY, Color.GRAY, Color.GREEN,
201 "Y", g);
202 drawGraph(buffers.get(2), fieldZ, Color.GRAY, Color.BLUE, "Z",
203 g);
204
205 }
206 }
207
208
209
210
211
212
213
214
215
216
217
218 private static List<List<Point>> scaleAccelerations(Accelerations acc,
219 Rectangle fieldSize) {
220
221 long timeFirst = acc.getFirstSampleTime();
222 long timeLast = acc.getLastSampleTime();
223
224 double maxAbsAcc = acc.getMaxAbsoluteAccelerationValue();
225
226 double graphWidth = fieldSize.getWidth();
227 double graphHeight = fieldSize.getHeight();
228
229 double verticalScalingFactor = (0.5 * graphHeight) / maxAbsAcc;
230
231 long gestureLength = timeLast - timeFirst;
232 double horizontalScalingFactor = graphWidth / gestureLength;
233
234 List<Point> bufferX = new Vector<Point>();
235 List<Point> bufferY = new Vector<Point>();
236 List<Point> bufferZ = new Vector<Point>();
237 Iterator<AccelerationSample> i = acc.getSamples().iterator();
238 while (i.hasNext()) {
239 AccelerationSample s = i.next();
240 Point point = new Point();
241
242 double xPos = horizontalScalingFactor
243 * (s.getTimeStamp() - timeFirst);
244 double yPos = (graphHeight / 2)
245 - (verticalScalingFactor * (s.getXAcceleration()));
246 point.setLocation(xPos, yPos);
247 bufferX.add(point);
248
249 point = new Point();
250 yPos = (graphHeight / 2)
251 - (verticalScalingFactor * (s.getYAcceleration()));
252 point.setLocation(xPos, yPos);
253 bufferY.add(point);
254
255 point = new Point();
256 yPos = (graphHeight / 2)
257 - (verticalScalingFactor * (s.getZAcceleration()));
258 point.setLocation(xPos, yPos);
259 bufferZ.add(point);
260 }
261 List<List<Point>> buffers = new Vector<List<Point>>();
262 buffers.add(bufferX);
263 buffers.add(bufferY);
264 buffers.add(bufferZ);
265 return buffers;
266 }
267
268
269
270
271
272
273
274
275
276
277
278
279
280 private static void drawPlane(Note plane, Rectangle field, Graphics g) {
281 if (plane != null) {
282 g.setColor(Color.BLACK);
283
284 for (Trace trace : plane.getTraces()) {
285 drawTrace(trace, 10, field, g);
286 }
287 }
288 }
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303 private static void drawTrace(Trace trace, int margin, Rectangle field, Graphics g) {
304
305
306
307 List<Point> buffer = new ArrayList<Point>();
308 for (org.sigtec.ink.Point point : trace.getPoints()) {
309 buffer.add(new Point((int) point.getX(), (int) point.getY()));
310 }
311
312 for (int i = 0; i < buffer.size() - 1; i++) {
313 g.drawLine((int) (buffer.get(i).getX() + field.getX()),
314 (int) (buffer.get(i).getY() + field.getY()), (int) (buffer
315 .get(i + 1).getX() + field.getX()), (int) (buffer
316 .get(i + 1).getY() + field.getY()));
317 }
318
319 if (buffer.size() > 0)
320 g.fillOval((int) (buffer.get(0).getX() + +field.getX()),
321 (int) (buffer.get(0).getY() + field.getY()), 5, 5);
322 }
323
324
325
326
327
328
329
330
331
332
333
334
335 private static List<Trace> scaleTraces(List<Trace> traces, int margin,
336 List<Rectangle> fields) {
337 List<Trace> tracesNew = new Vector<Trace>();
338 double scalingFactor = 0;
339
340 double maxXUsed = 0;
341 double maxYUsed = 0;
342 double minXAvailable = 100000;
343 double minYAvailable = 100000;
344 for (int i = 0; i < traces.size(); i++) {
345
346 Trace trace = traces.get(i);
347 Rectangle field = fields.get(i);
348
349 double maxFoundX = 0;
350 double minFoundX = 0;
351 double maxFoundY = 0;
352 double minFoundY = 0;
353 for (int j = 0; j < trace.getPoints().size(); j++) {
354 org.sigtec.ink.Point point = trace.getPoints().get(j);
355 if (point.getX() > maxFoundX)
356 maxFoundX = point.getX();
357 if (point.getY() > maxFoundY)
358 maxFoundY = point.getY();
359 if (point.getX() < minFoundX)
360 minFoundX = point.getX();
361 if (point.getY() < minFoundY)
362 minFoundY = point.getY();
363 }
364 double xSizeUsed = maxFoundX - minFoundX;
365 double ySizeUsed = maxFoundY - minFoundY;
366
367 if (xSizeUsed > maxXUsed)
368 maxXUsed = xSizeUsed;
369 if (ySizeUsed > maxYUsed)
370 maxYUsed = ySizeUsed;
371
372
373 double minAvailableX = field.getX() + margin;
374 double minAvailableY = field.getY() + margin;
375 double maxAvailableX = (field.getWidth() + field.getX()) - margin;
376 double maxAvailableY = (field.getHeight() + field.getY()) - margin;
377 double xSizeAvailable = maxAvailableX - minAvailableX;
378 double ySizeAvailable = maxAvailableY - minAvailableY;
379
380 if (xSizeAvailable < minXAvailable)
381 minXAvailable = xSizeAvailable;
382 if (ySizeAvailable < minYAvailable)
383 minYAvailable = ySizeAvailable;
384
385 }
386
387 scalingFactor = findScalingFactor(minXAvailable, maxXUsed,
388 minYAvailable, maxYUsed);
389
390 for (int i = 0; i < traces.size(); i++) {
391
392 Trace trace = traces.get(i);
393
394
395 double maxFoundX = 0;
396 double minFoundX = 0;
397 double maxFoundY = 0;
398 double minFoundY = 0;
399 for (int j = 0; j < trace.getPoints().size(); j++) {
400 org.sigtec.ink.Point point = trace.getPoints().get(j);
401 if (point.getX() > maxFoundX)
402 maxFoundX = point.getX();
403 if (point.getY() > maxFoundY)
404 maxFoundY = point.getY();
405 if (point.getX() < minFoundX)
406 minFoundX = point.getX();
407 if (point.getY() < minFoundY)
408 minFoundY = point.getY();
409 }
410
411
412 Trace traceNew = new Trace();
413 for (int k = 0; k < trace.getPoints().size(); k++) {
414 double xNew = scalingFactor
415 * (trace.getPoints().get(k).getX() - minFoundX)
416 + margin;
417 double yNew = scalingFactor
418 * (trace.getPoints().get(k).getY() - minFoundY)
419 + margin;
420 traceNew.add(new org.sigtec.ink.Point(xNew, yNew));
421 }
422 tracesNew.add(traceNew);
423 }
424 return tracesNew;
425 }
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440 private static double findScalingFactor(double xSizeAvailable, double xSizeUsed,
441 double ySizeAvailable, double ySizeUsed) {
442 double scalingFactor = xSizeAvailable / xSizeUsed;
443 if ((ySizeAvailable / ySizeUsed) < scalingFactor)
444
445
446 scalingFactor = ySizeAvailable / ySizeUsed;
447 return scalingFactor;
448 }
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466 private static void drawGraph(List<Point> data, Rectangle field, Color axisColor,
467 Color dataColor, String title, Graphics g) {
468
469
470 Color originalColor = g.getColor();
471
472 g.setColor(axisColor);
473 g.drawLine((int) field.getX(), (int) (field.getY() + (0.5 * field
474 .getHeight())), (int) (field.getX() + field.getWidth()),
475 (int) (field.getY() + (0.5 * field.getHeight())));
476 g.drawLine((int) field.getX(), (int) field.getY(), (int) field.getX(),
477 (int) (field.getY() + field.getHeight()));
478
479
480
481 g.setColor(dataColor);
482
483 Font originalFont = g.getFont();
484 Font font = new Font("Arial", Font.PLAIN, 10);
485 g.setFont(font);
486 g.drawString(title, (int) (field.getX() + (0.5 * field.getWidth())),
487 (int) (field.getY() + 15));
488 g.setFont(originalFont);
489
490 Point lastPoint = new Point();
491 if (data.size() > 0)
492 lastPoint.setLocation((int) data.get(0).getX(), (int) data.get(0)
493 .getY());
494 Iterator<Point> it = data.iterator();
495 while (it.hasNext()) {
496 Point p = it.next();
497 int oldX = (int) (field.getX() + lastPoint.getX());
498 int oldY = (int) (field.getY() + lastPoint.getY());
499 int newX = (int) (field.getX() + p.getX());
500 int newY = (int) (field.getY() + p.getY());
501 g.drawLine(oldX, oldY, newX, newY);
502 lastPoint = p;
503
504 }
505
506 g.setColor(originalColor);
507 }
508
509
510
511
512
513
514
515
516
517
518
519 public static List<Gesture<Note>> splitToPlanes(RecordedGesture3D gs) {
520 Iterator<Point3D> iterator = gs.iterator();
521
522
523
524 Trace traceXY = new Trace();
525 Trace traceYZ = new Trace();
526 Trace traceZX = new Trace();
527 Point3D point3d;
528
529 while (iterator.hasNext()) {
530 point3d = iterator.next();
531
532 traceXY.add(new org.sigtec.ink.Point(point3d.getX(), point3d.getY(), point3d.getTimeStamp()));
533 traceYZ.add(new org.sigtec.ink.Point(point3d.getY(), point3d.getZ(), point3d.getTimeStamp()));
534 traceZX.add(new org.sigtec.ink.Point(point3d.getZ(), point3d.getX(), point3d.getTimeStamp()));
535 }
536
537 Note noteXY = new Note();
538 Note noteYZ = new Note();
539 Note noteZX = new Note();
540
541 noteXY.add(traceXY);
542 noteYZ.add(traceYZ);
543 noteZX.add(traceZX);
544 List<Gesture<Note>> returnList = new ArrayList<Gesture<Note>>();
545
546 returnList.add(new GestureSample("XY-plane", noteXY));
547 returnList.add(new GestureSample("YZ-plane", noteYZ));
548 returnList.add(new GestureSample("ZX-plane", noteZX));
549
550 return returnList;
551 }
552 }