-
Notifications
You must be signed in to change notification settings - Fork 15
/
LeapMotionP5.pde
1087 lines (965 loc) · 30.5 KB
/
LeapMotionP5.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* LeapMotionP5
*
* LeapMotionP5 library for Processing. Copyright (c) 2012-2013 held jointly by the individual
* authors.
*
* LeapMotionP5 library for Processing is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free Software Foundation,
* either version 3 of the License, or (at your option) any later version.
*
* LeapMotionP5 for Processing is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with LeapMotionP5 library
* for Processing. If not, see http://www.gnu.org/licenses/.
*
* Leap Developer SDK. Copyright (C) 2012-2013 Leap Motion, Inc. All rights reserved.
*/
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.awt.Component;
import processing.core.PApplet;
import processing.core.PVector;
import com.leapmotion.leap.Config;
import com.leapmotion.leap.Controller;
import com.leapmotion.leap.Finger;
import com.leapmotion.leap.Frame;
import com.leapmotion.leap.Gesture.Type;
import com.leapmotion.leap.Hand;
import com.leapmotion.leap.Pointable;
import com.leapmotion.leap.ScreenList;
import com.leapmotion.leap.Tool;
import com.leapmotion.leap.Vector;
/**
* LeapMotionP5.java
*
* @author Marcel Schwittlick
* @modified 15.03.2013
*
*/
public class LeapMotionP5 {
private PApplet p;
private LeapMotionListener listener;
private Controller controller;
private Component component;
private String sdkVersion = "0.7.7";
private final float LEAP_WIDTH = 200.0f; // in mm
private final float LEAP_HEIGHT = 500.0f; // in mm
private final float LEAP_DEPTH = 200.0f; // in mm
protected Frame currentFrame;
protected LinkedList<Frame> lastFrames;
protected CopyOnWriteArrayList<Frame> oldFrames;
protected LinkedList<Controller> oldControllers;
protected ConcurrentSkipListMap<Date, Frame> lastFramesInclProperTimestamps;
protected HashMap<Integer, Finger> lastDetectedFinger;
protected HashMap<Integer, Pointable> lastDetectedPointable;
protected HashMap<Integer, Hand> lastDetectedHand;
protected HashMap<Integer, Tool> lastDetectedTool;
private int activeScreenNr = 0;
private Finger velocityOffsetTestFinger;
/**
* this class gives you some high level access to the data tracked and recorded by the leap. it
* gives you a different way of access than the original leap sdk and transoforms all data into
* processing equivalent datatypes.
*
* @param p PApplet the processing applet
*/
public LeapMotionP5(PApplet p) {
this.p = p;
this.listener = new LeapMotionListener(this);
this.controller = new Controller();
this.controller.setPolicyFlags(Controller.PolicyFlag.POLICY_BACKGROUND_FRAMES);
this.controller.addListener(listener);
this.lastDetectedFinger = new HashMap<Integer, Finger>();
this.lastDetectedPointable = new HashMap<Integer, Pointable>();
this.lastDetectedHand = new HashMap<Integer, Hand>();
this.lastDetectedTool = new HashMap<Integer, Tool>();
this.lastDetectedFinger.put(0, new Finger());
this.lastDetectedPointable.put(0, new Pointable());
this.lastDetectedHand.put(0, new Hand());
this.lastDetectedTool.put(0, new Tool());
// this is neccessary because the velocity of all objects has an offset.
this.velocityOffsetTestFinger = new Finger();
}
/**
*
* @return
*/
public String getSDKVersion() {
return this.sdkVersion;
}
/**
*
* @param max
*/
public void maxFramesToRecord(int max) {
this.listener.maxFramesToRecord = max;
}
/**
* this prints out the current offset of the vectors from the sdk. this is just for information
* and will give you the position, velocity and acceleration offsets
*/
public void printCorrectionOffset() {
System.out.println("pos offset: " + getTip(this.velocityOffsetTestFinger));
System.out.println("velo offset: " + getVelocity(this.velocityOffsetTestFinger));
System.out.println("acc offset: " + getAcceleration(this.velocityOffsetTestFinger));
}
/**
*
*/
public void stop() {
this.controller.removeListener(this.listener);
this.p.stop();
}
/**
* this returns a pvector containing the velocity offset. the problems the velocity offset has
* with it, is that the velocity is slightly shiftet. for example if you shouldnt have any
* velocity, because the finger is stanging still its returning a velocity that is initialized
* with a new Finger object. this should be fixed with the upcoming sdk releases (i hope) *
*
* @return PVector containing the velocity offset
*/
public PVector velocityOffset() {
return vectorToPVector(this.velocityOffsetTestFinger.tipVelocity());
}
public PVector positionOffset() {
return vectorToPVector(this.velocityOffsetTestFinger.tipPosition());
}
/**
* this retuns an pvector containing the acceleration offset, that has to be substracted from
* every vector returned from the library. unfortunately the leap sdk has a little bug there.
*
* @return PVector containing the acceleration offset
*/
public PVector accelerationOffset() {
return getAcceleration(this.velocityOffsetTestFinger);
}
public void enableGesture(Type gestureName) {
this.controller.enableGesture(gestureName);
}
public void disableGesture(Type gesture) {
this.controller.enableGesture(gesture, false);
}
public boolean isEnabled(Type gesture) {
return this.controller.isGestureEnabled(gesture);
}
/**
* this returns the parent applet of the library - the processing applet.
*
* @return PApplet parent
*/
public PApplet getParent() {
return this.p;
}
/**
* returns the controller of the leap sdk
*
* @return Controller controller
*/
public Controller getController() {
try {
return this.controller;
}
catch (Exception e) {
System.err
.println("Can not return controller not initialized. Returning new Controller object");
System.out.println(e);
return new Controller();
}
}
/**
* returns the most current frame from the leap sdk. a frame contains every tracked data from the
* leap about your fingers.
*
* @return Frame the leap frame
*/
public Frame getFrame() {
try {
return this.currentFrame;
}
catch (Exception e) {
System.err.println("Can not return current frame. Returning new Frame object instead");
System.err.println(e);
return new Frame();
}
}
/**
* returns a frame by id.
*
* @param id the id of the frame you want
* @return Frame the frame which id you passed as a parameter. if the frame with the id you asked
* for is not currently saved anymore you'll get a new Frame object.
*/
public Frame getFrame(int id) {
Frame returnFrame = new Frame();
for (Frame frame : getFrames()) {
if (frame.id() >= id) {
returnFrame = frame;
}
}
return returnFrame;
}
/**
* returns the frame before the most current frame.
*
* @return
*/
public Frame getLastFrame() {
return getFrames().get(getFrames().size() - 2);
}
public Controller getLastController() {
return getLastControllers().get(getLastControllers().size() - 40);
}
/**
* returns the frame that was before the frame you passed.
*
* @param frame
* @return the frame that was recorded right before the frame you passed.
*/
public Frame getFrameBeforeFrame(Frame frame) {
Frame frameBefore = null;
for (Frame of : getFrames()) {
if (of.id() == frame.id() - 1) {
frameBefore = of;
}
}
return frameBefore;
}
/**
* returns a CopyOnWriteArrayList<Frame> containing all recently buffered frames.
*
* @return a CopyOnWriteArrayList containing the newest elements
*/
public CopyOnWriteArrayList<Frame> getFrames() {
try {
return this.oldFrames;
}
catch (Exception e) {
System.err.println("Can not return list of last frames. Returning empty list instead.");
System.err.println(e);
return new CopyOnWriteArrayList<Frame>();
}
}
public LinkedList<Controller> getLastControllers() {
return this.oldControllers;
}
/**
* returns a linkedlist containing the last buffered frame
*
* @param frameCount the number of last frames
* @return a list containing all last frames
*/
public LinkedList<Frame> getFrames(int frameCount) {
LinkedList<Frame> frames = new LinkedList<Frame>();
for (int i = 0; i < frameCount; i++) {
if (getFrames().size() > frameCount) {
Frame fr = getFrames().get(getFrames().size() - frameCount + i);
frames.add(fr);
}
}
return frames;
}
/**
*
* @return
*/
public PVector getFingerPositionXYPlane() {
PVector fingerPositionXYPlane = new PVector();
Frame frame = getFrame();
if (frame.hands().isEmpty() == false) {
Hand hand = frame.hands().get(0);
if (hand.fingers().isEmpty() == false) {
Finger finger = hand.fingers().get(0);
fingerPositionXYPlane.x = transformLeapToScreenX(finger.tipPosition().getX());
fingerPositionXYPlane.y = transformLeapToScreenY(finger.tipPosition().getY());
}
}
return fingerPositionXYPlane;
}
/**
* converts the x coordinate from the leap space into the processing window space
*
* @param x leap-space
* @return processing-window space
*/
public float transformLeapToScreenX(float x) {
/*
* int startX = -243; int endX = 256; float valueMapped = PApplet.map(x, startX, endX, 0,
* p.width); return valueMapped;
*/
float c = this.p.width / 2.0f;
if (x > 0.0) {
return PApplet.lerp(c, this.p.width, x / LEAP_WIDTH);
} else {
return PApplet.lerp(c, 0.0f, -x / LEAP_WIDTH);
}
}
/**
* converts the y coordinate from the leap space into the processing window space
*
* @param y leap space
* @return processing-window space
*/
public float transformLeapToScreenY(float y) {
/*
* int startY = 50; int endY = 350; float valueMapped = PApplet.map(y, startY, endY, 0,
* p.height); return valueMapped;
*/
return PApplet.lerp(this.p.height, 0.0f, y / LEAP_HEIGHT);
}
/**
* converts the z coordinate from the leap space into the processing window space
*
* @param z leap space
* @return processing window space
*/
public float transformLeapToScreenZ(float z) {
/*
* int startZ = -51; int endZ = 149; float valueMapped = PApplet.map(z, startZ, endZ, 0,
* p.width); return valueMapped;
*/
return PApplet.lerp(0, this.p.width, z / LEAP_DEPTH);
}
/**
* converts a vector from the leap space into the processing window space
*
* @param vector from the leap sdk containing a position in the leap space
* @return the vector in PVector data type containing the same position in processing window space
*/
public PVector vectorToPVector(Vector vector) {
return convertLeapToScreenDimension(vector.getX(), vector.getY(), vector.getZ());
}
/**
* converts x, y and z coordinates of the leap to the dimensions of your sketch
*
* @param x x position in leap world coordinate system
* @param y y position in leap world coordinate system
* @param z z position in leap world coordinate system
* @return PVector the pvector of the point you passed in converted to the dimensions of your
* processing sketch window
*/
public PVector convertLeapToScreenDimension(float x, float y, float z) {
PVector positionRelativeToFrame = new PVector();
positionRelativeToFrame.x = transformLeapToScreenX(x);
positionRelativeToFrame.y = transformLeapToScreenY(y);
positionRelativeToFrame.z = transformLeapToScreenZ(z);
return positionRelativeToFrame;
}
/**
* returns an arraylist containing all currently tracked hands
*
* @return ArrayList<Hand> an arraylist containing all currently tracked hands
*/
public ArrayList<Hand> getHandList() {
ArrayList<Hand> hands = new ArrayList<Hand>();
Frame frame = getFrame();
if (frame.hands().isEmpty() == false) {
for (Hand hand : frame.hands()) {
hands.add(hand);
}
}
return hands;
}
/**
* returns all hands tracked in the frame you passed
*
* @param frame the frame from which to find out all tracked hands
* @return arraylist containing all hands from the passed frame
*/
public ArrayList<Hand> getHandList(Frame frame) {
ArrayList<Hand> hands = new ArrayList<Hand>();
try {
if (frame.hands().isEmpty() == false) {
for (Hand hand : frame.hands()) {
if (hand.isValid()) {
hands.add(hand);
}
}
}
}
catch (Exception e) {
// ignore
}
return hands;
}
/**
* gets a hand by number. the number is indicated by the order the hand appeared in the leap. so
* the first hand tracked has the nr 0 and the second one the number 1. once one hand of them two
* leaves the leap the one hand left has the nr 0. this is implemented like that because the leap
* is loosing track of the id's of hand to easily.
*
* @param handNr nr of the hand
* @return
*/
public Hand getHand(int handNr) {
Hand returnHand = null;
if (!getHandList().isEmpty()) {
this.lastDetectedHand.put(handNr, getHandList().get(handNr));
}
// returnHand = lastDetectedHand.get(handNr);
int downCounter = 0;
while (returnHand == null) {
returnHand = this.lastDetectedHand.get(handNr - downCounter);
downCounter++;
}
return returnHand;
}
/**
* returns a hand by id in the frame you passed.
*
* @param id
* @param frame
* @return
*/
public Hand getHandById(int id, Frame frame) {
Hand returnHand = null;
for (Hand hand : getHandList(frame)) {
if (hand.id() == id) {
returnHand = hand;
}
}
return returnHand;
}
/**
*
* @return
*/
public float getScaleFactor() {
return getFrame().scaleFactor(getLastFrame());
}
/**
*
* @return
*/
public float getScaleFactor(Frame frame) {
return getFrame().scaleFactor(frame);
}
/**
* returns averaged translation of all points tracked by the leap in comparison to the last frame
*
* @return
*/
public PVector getTranslation() {
PVector translation = vectorToPVector(getFrame().translation(getLastFrame()));
translation.sub(velocityOffset());
return translation;
}
/**
* returns averaged translation of all points tracked by the leap in comparison to the frame you
* passed in the method
*
* @return
*/
public PVector getTranslation(Frame frame) {
PVector translation = vectorToPVector(getFrame().translation(frame));
translation.sub(velocityOffset());
return translation;
}
/**
* returns the pitch of the hand you passed
*
* @param hand the hand you want the pitch of
* @return a float value containing the pitch of the hand
*/
public float getPitch(Hand hand) {
// return PApplet.map((float) Math.toDegrees(hand.direction().pitch()), 0, 22, 0,
// PConstants.TWO_PI);
return (float) Math.toDegrees(hand.direction().pitch());
}
/**
* returns the roll of the hand you passed
*
* @param hand the hand you want the roll of
* @return a float value containing the roll of the hand
*/
public float getRoll(Hand hand) {
// return -PApplet.map((float) Math.toDegrees(hand.direction().roll()), 0, 180, 0,
// PConstants.TWO_PI);
return (float) Math.toDegrees(hand.palmNormal().roll());
}
/**
* returns the yaw of the hand you passed
*
* @param hand the hand you want the yaw of
* @return a float value containing the yaw of the hand
*/
public float getYaw(Hand hand) {
return (float) Math.toDegrees(hand.direction().yaw());
}
/**
* returns a PVector containing the direction of the hand
*
* @param hand the hand you want the direction of
* @return PVector direction of the hand
*/
public PVector getDirection(Hand hand) {
PVector dir = vectorToPVector(hand.direction());
dir.sub(positionOffset());
return dir;
}
/**
* returns a PVector containing the position of the hand
*
* @param hand the hand you want the position of
* @return PVector position of the hand
*/
public PVector getPosition(Hand hand) {
return vectorToPVector(hand.palmPosition());
}
/**
* retrusn the normal of the palm of the hand
*
* @param hand the hand you want the normal of the handpalm of
* @return a PVector containing the normal of thepalm of the hand
*/
public PVector getNormal(Hand hand) {
PVector normal = vectorToPVector(hand.palmNormal());
normal.sub(positionOffset());
return normal;
}
/**
* returns the velocity of the palm of the hand you passed in
*
* @param hand the hand of which palm you want the velocity of
* @return a PVector containing the velocity of the hand
*/
public PVector getVelocity(Hand hand) {
PVector velo = vectorToPVector(hand.palmVelocity());
velo.sub(velocityOffset());
return velo;
}
/**
* access to the acceleration of the hand you passed in.
*
* @param hand the hand you want the acceleration of
* @return a PVector containing the acceleration of the hand you passed in
*/
public PVector getAcceleration(Hand hand) {
PVector acceleration = null;
Frame currentFrame = getFrame();
Frame lastFrame = getFrameBeforeFrame(currentFrame);
PVector currentVelo = new PVector();
PVector lastVelo = new PVector();
try {
currentVelo = getVelocity(hand);
lastVelo = getVelocity(getHandById(hand.id(), lastFrame));
}
catch (Exception e) {
// ignore
}
currentVelo.sub(lastVelo);
currentVelo.div(2);
acceleration = currentVelo;
return acceleration;
}
/**
*
* @param hand
* @return
*/
public PVector getSphereCenter(Hand hand) {
return vectorToPVector(hand.sphereCenter());
}
/**
*
* @param hand
* @return
*/
public float getSphereRadius(Hand hand) {
return hand.sphereRadius();
}
/**
* access to all fingers that are currently tracked
*
* @return ArrayList<Finger> an arraylist containing all currently tracked fingers
*/
public ArrayList<Finger> getFingerList() {
ArrayList<Finger> fingers = new ArrayList<Finger>();
Frame frame = getFrame();
if (frame.hands().isEmpty() == false) {
for (Hand hand : frame.hands()) {
fingers.addAll(getFingerList(hand));
}
}
return fingers;
}
/**
* access to all tracked fingers in the frame you passed in
*
* @param frame the frame you want all tracked fingers of
* @return an arraylist containing all tracked fingers
*/
public ArrayList<Finger> getFingerList(Frame frame) {
ArrayList<Finger> fingers = new ArrayList<Finger>();
if (frame.hands().isEmpty() == false) {
for (Hand hand : frame.hands()) {
fingers.addAll(getFingerList(hand));
}
}
return fingers;
}
/**
* access to all fingers of the hand you passed in
*
* @param hand the hand you want all tracked fingers of
* @return an arraylist containing all tracked fingers of the hand
*/
public ArrayList<Finger> getFingerList(Hand hand) {
ArrayList<Finger> fingers = new ArrayList<Finger>();
for (Finger finger : hand.fingers()) {
fingers.add(finger);
}
return fingers;
}
/**
* returns the finger by number. the fingers are numbered by the occurence in the leap.
*
* @param fingerNr
* @return
*/
public Finger getFinger(int fingerNr) {
Finger returnFinger = null;
if (getFingerList().size() > fingerNr) {
this.lastDetectedFinger.put(fingerNr, getFingerList().get(fingerNr));
}
// returnFinger = lastDetectedFinger.get(fingerNr);
int downCounter = 0;
while (returnFinger == null) {
returnFinger = this.lastDetectedFinger.get(fingerNr - downCounter);
downCounter++;
}
return returnFinger;
}
/**
*
* @param id
* @param frame
* @return
*/
public Finger getFingerById(int id, Frame frame) {
Finger returnFinger = null;
for (Finger finger : getFingerList(frame)) {
if (finger.id() == id) {
returnFinger = finger;
}
}
return returnFinger;
}
/**
* returns the tip position of the passed pointable
*
* @param pointable the pointable you want the tippoisition of
* @return a PVector containing the position of the tip of the pointable
*/
public PVector getTip(Pointable pointable) {
return convertLeapToScreenDimension(pointable.tipPosition().getX(), pointable.tipPosition()
.getY(), pointable.tipPosition().getZ());
}
/**
* sets the current screen for gettings the calibrated points. I should rewrite this, but nobody
* is gonna read it anyway. arr.
*
* @param screenNr
*/
public void setActiveScreen(int screenNr) {
this.activeScreenNr = screenNr;
}
/**
* to use this utility you have to have the leap calirated to your screen
*
* @param pointable the finger you want the intersection with your screen from
* @param screenNr the number of the screen you calibrated
* @return
*/
public PVector getTipOnScreen(Pointable pointable) {
PVector pos;
ScreenList sl = this.controller.locatedScreens();
com.leapmotion.leap.Screen calibratedScreen = sl.get(activeScreenNr);
Vector loc = calibratedScreen.intersect(pointable, true);
float _x = PApplet.map(loc.getX(), 0, 1, 0, this.p.displayWidth);
_x -= this.component.getLocationOnScreen().x;
float _y = PApplet.map(loc.getY(), 0, 1, this.p.displayHeight, 0);
_y -= this.component.getLocationOnScreen().y;
pos = new PVector(_x, _y);
return pos;
}
/**
* returns the velocity of a finger on the screen
*
* @param pointable
* @return
*/
public PVector getVelocityOnScreen(Pointable pointable) {
Vector loc = new Vector();
Vector oldLoc = new Vector();
try {
oldLoc =
getLastController().locatedScreens().get(this.activeScreenNr)
.intersect(getPointableById(pointable.id(), getLastFrame()), true);
loc = this.controller.locatedScreens().get(this.activeScreenNr).intersect(pointable, true);
}
catch (NullPointerException e) {
// dirty dirty hack to keep the programm runing. i like it.
}
float _x = PApplet.map(loc.getX(), 0, 1, 0, this.p.displayWidth);
_x -= this.component.getLocationOnScreen().x;
float _y = PApplet.map(loc.getY(), 0, 1, this.p.displayHeight, 0);
_y -= this.component.getLocationOnScreen().y;
float _x2 = PApplet.map(oldLoc.getX(), 0, 1, 0, this.p.displayWidth);
_x2 -= this.component.getLocationOnScreen().x;
float _y2 = PApplet.map(oldLoc.getY(), 0, 1, this.p.displayHeight, 0);
_y2 -= this.component.getLocationOnScreen().y;
return new PVector(_x - _x2, _y - _y2);
}
/**
* returns the origin of the pointable. the origin is the place where the pointable leaves the
* body of the hand.
*
* @param pointable the pointable you want the origin of
* @return a PVector containing the position of the origin of the passed pointable
*/
public PVector getOrigin(Pointable pointable) {
Vector anklePos;
float length = pointable.length();
PVector direction = new PVector();
direction.x = pointable.direction().getX();
direction.y = pointable.direction().getY();
direction.z = pointable.direction().getZ();
direction.mult(length);
anklePos =
new Vector(pointable.tipPosition().getX() - direction.x, pointable.tipPosition().getY()
- direction.y, pointable.tipPosition().getZ() - direction.z);
return vectorToPVector(anklePos);
}
/**
* returns the velocity of the pointbale
*
* @param pointable the pointable you want the velocity of
* @return a PVector containing the velocity of the tip of the pointble
*/
public PVector getVelocity(Pointable pointable) {
PVector velo = vectorToPVector(pointable.tipVelocity());
velo.sub(velocityOffset());
return velo;
}
/**
* calculates the direction of the passed pointable
*
* @param pointable the pointable you want the direction of
* @return a PVector containing the direction of the pointable
*/
public PVector getDirection(Pointable pointable) {
return vectorToPVector(pointable.direction());
}
/**
* passes the length of a pointable though.
*
* @param pointable
* @return
*/
public float getLength(Pointable pointable) {
return pointable.length();
}
/**
* passes the width of a pointable through
*
* @param pointable
* @return
*/
public float getWidth(Pointable pointable) {
return pointable.width();
}
/**
* calculates the acceleration of the pointable according to the velocity of the curent and the
* last frame
*
* @param pointable the pointable you want the acceleration of
* @return a PVector containing the acceleration of the tip of the passed pointable
*/
public PVector getAcceleration(Pointable pointable) {
PVector acceleration = null;
Frame currentFrame = getFrame();
Frame lastFrame = getFrameBeforeFrame(currentFrame);
PVector currentVelo = new PVector();
PVector lastVelo = new PVector();
try {
currentVelo = getVelocity(pointable);
lastVelo = getVelocity(getPointableById(pointable.id(), lastFrame));
}
catch (Exception e) {
// ignore
}
currentVelo.sub(lastVelo);
currentVelo.div(2);
acceleration = currentVelo;
return acceleration;
}
/**
* returns all pointables in the current frame
*
* @return ArrayList<Pointable> an arraylist containing all currently tracked pointables
*/
public ArrayList<Pointable> getPointableList() {
ArrayList<Pointable> pointables = new ArrayList<Pointable>();
Frame frame = getFrame();
if (frame.hands().isEmpty() == false) {
for (Hand hand : frame.hands()) {
pointables.addAll(getPointableList(hand));
}
}
return pointables;
}
/**
* returns all pointables of the passed framre
*
* @return ArrayList<Pointable> an arraylist containing all currently tracked pointables
*/
public ArrayList<Pointable> getPointableList(Frame frame) {
ArrayList<Pointable> pointables = new ArrayList<Pointable>();
if (frame.hands().isEmpty() == false) {
for (Hand hand : frame.hands()) {
pointables.addAll(getPointableList(hand));
}
}
return pointables;
}
/**
* returns all pointables of the passed hand
*
* @param hand the hand you want the pointables of
* @return an arraylist containing the pointables of the passed hand
*/
public ArrayList<Pointable> getPointableList(Hand hand) {
ArrayList<Pointable> pointables = new ArrayList<Pointable>();
for (Pointable pointable : hand.pointables()) {
pointables.add(pointable);
}
return pointables;
}
/**
* returns a pointable by its number. look up to the equivalent methods for hand/finger for
* documentation
*
* @param pointableNr the number of the pointable
* @return
*/
public Pointable getPointable(int pointableNr) {
Pointable returnPointable = null;
if (!getPointableList().isEmpty()) {
this.lastDetectedPointable.put(pointableNr, getPointableList().get(pointableNr));
}
// returnPointable = lastDetectedPointable.get(pointableNr);
int downCounter = 0;
while (returnPointable == null) {
returnPointable = this.lastDetectedPointable.get(pointableNr - downCounter);
downCounter++;
}
return returnPointable;
}
/**
* returns a pointable by id in the passed frame
*
* @param id the if of the pointbale
* @param frame the frame where to look for the pointable
* @return
*/
public Pointable getPointableById(int id, Frame frame) {
Pointable returnPointable = null;
for (Pointable pointable : getPointableList(frame)) {
if (pointable.id() == id) {
returnPointable = pointable;
}
}
return returnPointable;
}
/**
* calculates an arraylist containing all tools in the current frame
*
* @return
*/