├── README.md ├── examples ├── active_fingers │ └── active_fingers.pde ├── finger_to_pvector │ └── finger_to_pvector.pde ├── gesture_recognition │ └── gesture_recognition.pde ├── lowlevel_access │ └── lowlevel_access.pde ├── lowlevel_access_multiple_frames │ └── lowlevel_access_multiple_frames.pde ├── screen_calibration │ └── screen_calibration.pde └── velocity_graph │ └── velocity_graph.pde ├── library.properties ├── library ├── LeapJava.jar ├── LeapMotionP5.jar ├── macosx │ ├── libLeap.dylib │ └── libLeapJava.dylib ├── windows │ ├── Leap.dll │ └── LeapJava.dll └── windows64 │ ├── Leap.dll │ └── LeapJava.dll └── src └── com └── onformative └── leap ├── LeapMotionListener.java └── LeapMotionP5.java /README.md: -------------------------------------------------------------------------------- 1 | LeapMotionP5 2 | ====================== 3 | #### A Leap Motion Library for Processing 4 | 5 | Working with all Processing versions and all operating systems (OSX, Windows), with the newest version of the leap motion sdk. Moreover it is including a variety of gestures. 6 | Just download the library archive at the bottom of this readme and extract it into the libraries folder of your processing sketchbook and your're ready to go. 7 | 8 | Check http://www.onformative.com/lab/leapmotionp5 for additional information about the library. 9 | 10 | Download 11 | -------- 12 | Download from here https://github.com/mrzl/LeapMotionP5/archive/master.zip extract the folder in the archive into your processing libraries folder and rename it from LeapMotionP5-master to LeapMotionP5. After that restart Processing and the library should be included. Check the examples within the library. 13 | 14 | 15 | Examples 16 | -------- 17 | #### Basic Example 18 |
 19 | import com.onformative.leap.LeapMotionP5;
 20 | import com.leapmotion.leap.Finger;
 21 | 
 22 | LeapMotionP5 leap;
 23 | 
 24 | public void setup() {
 25 |   size(500, 500);
 26 |   leap = new LeapMotionP5(this);
 27 | }
 28 | 
 29 | public void draw() {
 30 |   background(0);
 31 |   fill(255);
 32 |   for (Finger finger : leap.getFingerList()) {
 33 |     PVector fingerPos = leap.getTip(finger);
 34 |     ellipse(fingerPos.x, fingerPos.y, 10, 10);
 35 |   }
 36 | }
 37 | 
 38 | public void stop() {
 39 |   leap.stop();
 40 | }
 41 | 
42 | 43 | #### Gesture Recognition 44 |
 45 | import com.leapmotion.leap.CircleGesture;
 46 | import com.leapmotion.leap.Gesture.State;
 47 | import com.leapmotion.leap.Gesture.Type;
 48 | import com.leapmotion.leap.Hand;
 49 | import com.leapmotion.leap.KeyTapGesture;
 50 | import com.leapmotion.leap.ScreenTapGesture;
 51 | import com.leapmotion.leap.SwipeGesture;
 52 | import com.onformative.leap.LeapMotionP5;
 53 | 
 54 | LeapMotionP5 leap;
 55 | String lastGesture =
 56 | "enabling gestures: \n'c' for CircleGesture\n's' for SwipeGesture\n'k' for KeyTapGesture\n't' for ScreenTapGesture";
 57 | 
 58 | public void setup() {
 59 |   size(500, 500);
 60 |   textSize(17);
 61 | 
 62 |   leap = new LeapMotionP5(this);
 63 | }
 64 | 
 65 | public void draw() {
 66 |   background(0);
 67 |   for (Hand hand : leap.getHandList()) {
 68 |     PVector handPos = leap.getPosition(hand);
 69 |     ellipse(handPos.x, handPos.y, 20, 20);
 70 |   }
 71 |   text(lastGesture, 30, 30);
 72 | }
 73 | 
 74 | public void circleGestureRecognized(CircleGesture gesture, String clockwiseness) {
 75 |   if (gesture.state() == State.STATE_STOP) {
 76 |     System.out.println("//////////////////////////////////////");
 77 |     System.out.println("Gesture type: " + gesture.type().toString());
 78 |     System.out.println("ID: " + gesture.id());
 79 |     System.out.println("Radius: " + gesture.radius());
 80 |     System.out.println("Normal: " + gesture.normal());
 81 |     System.out.println("Clockwiseness: " + clockwiseness);
 82 |     System.out.println("Turns: " + gesture.progress());
 83 |     System.out.println("Center: " + leap.convertVectorToPVector(gesture.center()));
 84 |     System.out.println("Duration: " + gesture.durationSeconds() + "s");
 85 |     System.out.println("//////////////////////////////////////");
 86 |     lastGesture = "Gesture type: " + gesture.type().toString() + "\n";
 87 |     lastGesture += "ID: " + gesture.id() + "\n";
 88 |     lastGesture += "Radius: " + gesture.radius() + "\n";
 89 |     lastGesture += "Normal: " + gesture.normal() + "\n";
 90 |     lastGesture += "Clockwiseness: " + clockwiseness + "\n";
 91 |     lastGesture += "Turns: " + gesture.progress() + "\n";
 92 |     lastGesture += "Center: " + leap.convertVectorToPVector(gesture.center()) + "\n";
 93 |     lastGesture += "Duration: " + gesture.durationSeconds() + "s" + "\n";
 94 |   } 
 95 |   else if (gesture.state() == State.STATE_START) {
 96 |   } 
 97 |   else if (gesture.state() == State.STATE_UPDATE) {
 98 |   }
 99 | }
100 | 
101 | public void swipeGestureRecognized(SwipeGesture gesture) {
102 |   if (gesture.state() == State.STATE_STOP) {
103 |     System.out.println("//////////////////////////////////////");
104 |     System.out.println("Gesture type: " + gesture.type());
105 |     System.out.println("ID: " + gesture.id());
106 |     System.out.println("Position: " + leap.convertVectorToPVector(gesture.position()));
107 |     System.out.println("Direction: " + gesture.direction());
108 |     System.out.println("Duration: " + gesture.durationSeconds() + "s");
109 |     System.out.println("Speed: " + gesture.speed());
110 |     System.out.println("//////////////////////////////////////");
111 |     lastGesture = "Gesture type: " + gesture.type().toString() + "\n";
112 |     lastGesture += "ID: " + gesture.id() + "\n";
113 |     lastGesture += "Position: " + leap.convertVectorToPVector(gesture.position()) + "\n";
114 |     lastGesture += "Direction: " + gesture.direction() + "\n";
115 |     lastGesture += "Speed: " + gesture.speed() + "\n";
116 |     lastGesture += "Duration: " + gesture.durationSeconds() + "s" + "\n";
117 |   } 
118 |   else if (gesture.state() == State.STATE_START) {
119 |   } 
120 |   else if (gesture.state() == State.STATE_UPDATE) {
121 |   }
122 | }
123 | 
124 | public void screenTapGestureRecognized(ScreenTapGesture gesture) {
125 |   if (gesture.state() == State.STATE_STOP) {
126 |     System.out.println("//////////////////////////////////////");
127 |     System.out.println("Gesture type: " + gesture.type());
128 |     System.out.println("ID: " + gesture.id());
129 |     System.out.println("Position: " + leap.convertVectorToPVector(gesture.position()));
130 |     System.out.println("Direction: " + gesture.direction());
131 |     System.out.println("Duration: " + gesture.durationSeconds() + "s");
132 |     System.out.println("//////////////////////////////////////");
133 |     lastGesture = "Gesture type: " + gesture.type().toString() + "\n";
134 |     lastGesture += "ID: " + gesture.id() + "\n";
135 |     lastGesture += "Position: " + leap.convertVectorToPVector(gesture.position()) + "\n";
136 |     lastGesture += "Direction: " + gesture.direction() + "\n";
137 |     lastGesture += "Duration: " + gesture.durationSeconds() + "s" + "\n";
138 |   } 
139 |   else if (gesture.state() == State.STATE_START) {
140 |   } 
141 |   else if (gesture.state() == State.STATE_UPDATE) {
142 |   }
143 | }
144 | 
145 | public void KeyTapGestureRecognized(KeyTapGesture gesture) {
146 |   if (gesture.state() == State.STATE_STOP) {
147 |     System.out.println("//////////////////////////////////////");
148 |     System.out.println("Gesture type: " + gesture.type());
149 |     System.out.println("ID: " + gesture.id());
150 |     System.out.println("Position: " + leap.convertVectorToPVector(gesture.position()));
151 |     System.out.println("Direction: " + gesture.direction());
152 |     System.out.println("Duration: " + gesture.durationSeconds() + "s");
153 |     System.out.println("//////////////////////////////////////");
154 |     lastGesture = "Gesture type: " + gesture.type().toString() + "\n";
155 |     lastGesture += "ID: " + gesture.id() + "\n";
156 |     lastGesture += "Position: " + leap.convertVectorToPVector(gesture.position()) + "\n";
157 |     lastGesture += "Direction: " + gesture.direction() + "\n";
158 |     lastGesture += "Duration: " + gesture.durationSeconds() + "s" + "\n";
159 |   } 
160 |   else if (gesture.state() == State.STATE_START) {
161 |   } 
162 |   else if (gesture.state() == State.STATE_UPDATE) {
163 |   }
164 | }
165 | 
166 | public void keyPressed() {
167 |   if (key == 'c') {
168 |     if (leap.isEnabled(Type.TYPE_CIRCLE)) {
169 |       leap.disableGesture(Type.TYPE_CIRCLE);
170 |       lastGesture = "Circle Gesture disabled.";
171 |     } 
172 |     else {
173 |       leap.enableGesture(Type.TYPE_CIRCLE);
174 |       lastGesture = "Circle Gesture enabled.";
175 |     }
176 |   }
177 | 
178 |   if (key == 's') {
179 |     if (leap.isEnabled(Type.TYPE_SWIPE)) {
180 |       leap.disableGesture(Type.TYPE_SWIPE);
181 |       lastGesture = "Swipe Gesture disabled.";
182 |     } 
183 |     else {
184 |       leap.enableGesture(Type.TYPE_SWIPE);
185 |       lastGesture = "Swipe Gesture enabled.";
186 |     }
187 |   }
188 | 
189 |   if (key == 'k') {
190 |     if (leap.isEnabled(Type.TYPE_KEY_TAP)) {
191 |       leap.disableGesture(Type.TYPE_KEY_TAP);
192 |       lastGesture = "KeyTap Gesture disabled.";
193 |     } 
194 |     else {
195 |       leap.enableGesture(Type.TYPE_KEY_TAP);
196 |       lastGesture = "KeyTap Gesture enabled.";
197 |     }
198 |   }
199 | 
200 |   if (key == 't') {
201 |     if (leap.isEnabled(Type.TYPE_SCREEN_TAP)) {
202 |       leap.disableGesture(Type.TYPE_SCREEN_TAP);
203 |       lastGesture = "ScreenTap Gesture disabled. ";
204 |     } 
205 |     else {
206 |       leap.enableGesture(Type.TYPE_SCREEN_TAP);
207 |       lastGesture = "ScreenTap Gesture enabled. ";
208 |     }
209 |   }
210 | }
211 | public void stop() {
212 |   leap.stop();
213 | }
214 | 
215 | 
216 | 
217 | 218 | License 219 | ------- 220 |
221 | LeapMotionP5 library for Processing.
222 | Copyright (c) 2012-2013 held jointly by the individual authors.
223 | 
224 | LeapMotionP5 library for Processing is free software: you can redistribute it and/or
225 | modify it under the terms of the GNU General Public License as published by
226 | the Free Software Foundation, either version 3 of the License, or
227 | (at your option) any later version.
228 | 
229 | LeapMotionP5 library for Processing is distributed in the hope that it will be
230 | useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
231 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
232 | GNU General Public License for more details.
233 | 
234 | You should have received a copy of the GNU General Public License
235 | along with LeapMotionP5 library for Processing.  If not, see http://www.gnu.org/licenses/.
236 | 
237 | 238 |
239 | Leap Developer SDK.
240 | Copyright (C) 2012-2013 Leap Motion, Inc. All rights reserved.
241 | 
242 | NOTICE: This developer release of Leap Motion, Inc. software is confidential
243 | and intended for very limited distribution. Parties using this software must
244 | accept the SDK Agreement prior to obtaining this software and related tools.
245 | This software is subject to copyright.
246 | 
247 | -------------------------------------------------------------------------------- /examples/active_fingers/active_fingers.pde: -------------------------------------------------------------------------------- 1 | import com.onformative.leap.LeapMotionP5; 2 | import com.leapmotion.leap.Finger; 3 | 4 | LeapMotionP5 leap; 5 | 6 | public void setup() { 7 | size(500, 500); 8 | leap = new LeapMotionP5(this); 9 | } 10 | 11 | public void draw() { 12 | background(0); 13 | fill(255); 14 | for (Finger finger : leap.getFingerList()) { 15 | PVector fingerPos = leap.getTip(finger); 16 | ellipse(fingerPos.x, fingerPos.y, 10, 10); 17 | } 18 | } 19 | 20 | public void stop() { 21 | leap.stop(); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /examples/finger_to_pvector/finger_to_pvector.pde: -------------------------------------------------------------------------------- 1 | import com.onformative.leap.LeapMotionP5; 2 | 3 | LeapMotionP5 leap; 4 | 5 | void setup() { 6 | size(500, 500); 7 | leap = new LeapMotionP5(this); 8 | } 9 | 10 | void draw() { 11 | background(0); 12 | PVector fingerPos = leap.getTip(leap.getFinger(0)); 13 | ellipse(fingerPos.x, fingerPos.y, 20, 20); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /examples/gesture_recognition/gesture_recognition.pde: -------------------------------------------------------------------------------- 1 | import com.leapmotion.leap.CircleGesture; 2 | import com.leapmotion.leap.Gesture.State; 3 | import com.leapmotion.leap.Gesture.Type; 4 | import com.leapmotion.leap.Hand; 5 | import com.leapmotion.leap.KeyTapGesture; 6 | import com.leapmotion.leap.ScreenTapGesture; 7 | import com.leapmotion.leap.SwipeGesture; 8 | import com.onformative.leap.LeapMotionP5; 9 | 10 | LeapMotionP5 leap; 11 | String lastGesture = 12 | "enabling gestures: \n'c' for CircleGesture\n's' for SwipeGesture\n'k' for KeyTapGesture\n't' for ScreenTapGesture"; 13 | 14 | public void setup() { 15 | size(500, 500); 16 | textSize(17); 17 | 18 | leap = new LeapMotionP5(this); 19 | } 20 | 21 | public void draw() { 22 | background(0); 23 | for (Hand hand : leap.getHandList()) { 24 | PVector handPos = leap.getPosition(hand); 25 | ellipse(handPos.x, handPos.y, 20, 20); 26 | } 27 | text(lastGesture, 30, 30); 28 | } 29 | 30 | public void circleGestureRecognized(CircleGesture gesture, String clockwiseness) { 31 | if (gesture.state() == State.STATE_STOP) { 32 | System.out.println("//////////////////////////////////////"); 33 | System.out.println("Gesture type: " + gesture.type().toString()); 34 | System.out.println("ID: " + gesture.id()); 35 | System.out.println("Radius: " + gesture.radius()); 36 | System.out.println("Normal: " + gesture.normal()); 37 | System.out.println("Clockwiseness: " + clockwiseness); 38 | System.out.println("Turns: " + gesture.progress()); 39 | System.out.println("Center: " + leap.vectorToPVector(gesture.center())); 40 | System.out.println("Duration: " + gesture.durationSeconds() + "s"); 41 | System.out.println("//////////////////////////////////////"); 42 | lastGesture = "Gesture type: " + gesture.type().toString() + "\n"; 43 | lastGesture += "ID: " + gesture.id() + "\n"; 44 | lastGesture += "Radius: " + gesture.radius() + "\n"; 45 | lastGesture += "Normal: " + gesture.normal() + "\n"; 46 | lastGesture += "Clockwiseness: " + clockwiseness + "\n"; 47 | lastGesture += "Turns: " + gesture.progress() + "\n"; 48 | lastGesture += "Center: " + leap.vectorToPVector(gesture.center()) + "\n"; 49 | lastGesture += "Duration: " + gesture.durationSeconds() + "s" + "\n"; 50 | } 51 | else if (gesture.state() == State.STATE_START) { 52 | } 53 | else if (gesture.state() == State.STATE_UPDATE) { 54 | } 55 | } 56 | 57 | public void swipeGestureRecognized(SwipeGesture gesture) { 58 | if (gesture.state() == State.STATE_STOP) { 59 | System.out.println("//////////////////////////////////////"); 60 | System.out.println("Gesture type: " + gesture.type()); 61 | System.out.println("ID: " + gesture.id()); 62 | System.out.println("Position: " + leap.vectorToPVector(gesture.position())); 63 | System.out.println("Direction: " + gesture.direction()); 64 | System.out.println("Duration: " + gesture.durationSeconds() + "s"); 65 | System.out.println("Speed: " + gesture.speed()); 66 | System.out.println("//////////////////////////////////////"); 67 | lastGesture = "Gesture type: " + gesture.type().toString() + "\n"; 68 | lastGesture += "ID: " + gesture.id() + "\n"; 69 | lastGesture += "Position: " + leap.vectorToPVector(gesture.position()) + "\n"; 70 | lastGesture += "Direction: " + gesture.direction() + "\n"; 71 | lastGesture += "Speed: " + gesture.speed() + "\n"; 72 | lastGesture += "Duration: " + gesture.durationSeconds() + "s" + "\n"; 73 | } 74 | else if (gesture.state() == State.STATE_START) { 75 | } 76 | else if (gesture.state() == State.STATE_UPDATE) { 77 | } 78 | } 79 | 80 | public void screenTapGestureRecognized(ScreenTapGesture gesture) { 81 | if (gesture.state() == State.STATE_STOP) { 82 | System.out.println("//////////////////////////////////////"); 83 | System.out.println("Gesture type: " + gesture.type()); 84 | System.out.println("ID: " + gesture.id()); 85 | System.out.println("Position: " + leap.vectorToPVector(gesture.position())); 86 | System.out.println("Direction: " + gesture.direction()); 87 | System.out.println("Duration: " + gesture.durationSeconds() + "s"); 88 | System.out.println("//////////////////////////////////////"); 89 | lastGesture = "Gesture type: " + gesture.type().toString() + "\n"; 90 | lastGesture += "ID: " + gesture.id() + "\n"; 91 | lastGesture += "Position: " + leap.vectorToPVector(gesture.position()) + "\n"; 92 | lastGesture += "Direction: " + gesture.direction() + "\n"; 93 | lastGesture += "Duration: " + gesture.durationSeconds() + "s" + "\n"; 94 | } 95 | else if (gesture.state() == State.STATE_START) { 96 | } 97 | else if (gesture.state() == State.STATE_UPDATE) { 98 | } 99 | } 100 | 101 | public void KeyTapGestureRecognized(KeyTapGesture gesture) { 102 | if (gesture.state() == State.STATE_STOP) { 103 | System.out.println("//////////////////////////////////////"); 104 | System.out.println("Gesture type: " + gesture.type()); 105 | System.out.println("ID: " + gesture.id()); 106 | System.out.println("Position: " + leap.vectorToPVector(gesture.position())); 107 | System.out.println("Direction: " + gesture.direction()); 108 | System.out.println("Duration: " + gesture.durationSeconds() + "s"); 109 | System.out.println("//////////////////////////////////////"); 110 | lastGesture = "Gesture type: " + gesture.type().toString() + "\n"; 111 | lastGesture += "ID: " + gesture.id() + "\n"; 112 | lastGesture += "Position: " + leap.vectorToPVector(gesture.position()) + "\n"; 113 | lastGesture += "Direction: " + gesture.direction() + "\n"; 114 | lastGesture += "Duration: " + gesture.durationSeconds() + "s" + "\n"; 115 | } 116 | else if (gesture.state() == State.STATE_START) { 117 | } 118 | else if (gesture.state() == State.STATE_UPDATE) { 119 | } 120 | } 121 | 122 | public void keyPressed() { 123 | if (key == 'c') { 124 | if (leap.isEnabled(Type.TYPE_CIRCLE)) { 125 | leap.disableGesture(Type.TYPE_CIRCLE); 126 | lastGesture = "Circle Gesture disabled."; 127 | } 128 | else { 129 | leap.enableGesture(Type.TYPE_CIRCLE); 130 | lastGesture = "Circle Gesture enabled."; 131 | } 132 | } 133 | 134 | if (key == 's') { 135 | if (leap.isEnabled(Type.TYPE_SWIPE)) { 136 | leap.disableGesture(Type.TYPE_SWIPE); 137 | lastGesture = "Swipe Gesture disabled."; 138 | } 139 | else { 140 | leap.enableGesture(Type.TYPE_SWIPE); 141 | lastGesture = "Swipe Gesture enabled."; 142 | } 143 | } 144 | 145 | if (key == 'k') { 146 | if (leap.isEnabled(Type.TYPE_KEY_TAP)) { 147 | leap.disableGesture(Type.TYPE_KEY_TAP); 148 | lastGesture = "KeyTap Gesture disabled."; 149 | } 150 | else { 151 | leap.enableGesture(Type.TYPE_KEY_TAP); 152 | lastGesture = "KeyTap Gesture enabled."; 153 | } 154 | } 155 | 156 | if (key == 't') { 157 | if (leap.isEnabled(Type.TYPE_SCREEN_TAP)) { 158 | leap.disableGesture(Type.TYPE_SCREEN_TAP); 159 | lastGesture = "ScreenTap Gesture disabled. "; 160 | } 161 | else { 162 | leap.enableGesture(Type.TYPE_SCREEN_TAP); 163 | lastGesture = "ScreenTap Gesture enabled. "; 164 | } 165 | } 166 | } 167 | public void stop() { 168 | leap.stop(); 169 | } 170 | 171 | -------------------------------------------------------------------------------- /examples/lowlevel_access/lowlevel_access.pde: -------------------------------------------------------------------------------- 1 | import com.onformative.leap.LeapMotionP5; 2 | 3 | LeapMotionP5 leap; 4 | 5 | public void setup() { 6 | size(500, 500); 7 | leap = new LeapMotionP5(this); 8 | } 9 | 10 | public void draw() { 11 | com.leapmotion.leap.Frame frame = leap.getFrame(); 12 | // do some processing of the frame 13 | // this is the same frame you'd get if you would use the callback 14 | } 15 | 16 | public void stop() { 17 | leap.stop(); 18 | } 19 | -------------------------------------------------------------------------------- /examples/lowlevel_access_multiple_frames/lowlevel_access_multiple_frames.pde: -------------------------------------------------------------------------------- 1 | import com.onformative.leap.LeapMotionP5; 2 | 3 | LeapMotionP5 leap; 4 | 5 | public void setup() { 6 | size(500, 500); 7 | leap = new LeapMotionP5(this); 8 | } 9 | 10 | public void draw() { 11 | for (com.leapmotion.leap.Frame frame : leap.getFrames(200)) { 12 | // do something with the last 250 frames 13 | } 14 | } 15 | 16 | public void stop() { 17 | leap.stop(); 18 | } 19 | -------------------------------------------------------------------------------- /examples/screen_calibration/screen_calibration.pde: -------------------------------------------------------------------------------- 1 | import com.leapmotion.leap.Finger; 2 | import com.onformative.leap.LeapMotionP5; 3 | 4 | LeapMotionP5 leap; 5 | 6 | /** 7 | * this example shows how to use the screen calibration utility in processing. 8 | * in order to use this example you have to have your leap calibrated to your 9 | * screen. this will show you the intersection points between the extension of 10 | * your fingertips and your screen. 11 | * TIP: try moving the sketch window while you are pointing at your screen 12 | */ 13 | public void setup() { 14 | size(1000, 700, P3D); 15 | 16 | leap = new LeapMotionP5(this); 17 | fill(255); 18 | } 19 | 20 | public void draw() { 21 | background(0); 22 | for (Finger f : leap.getFingerList()) { 23 | PVector screenPos = leap.getTipOnScreen(f); 24 | ellipse(screenPos.x, screenPos.y, 10, 10); 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /examples/velocity_graph/velocity_graph.pde: -------------------------------------------------------------------------------- 1 | import com.onformative.leap.LeapMotionP5; 2 | import java.util.*; 3 | 4 | LeapMotionP5 leap; 5 | LinkedList values; 6 | 7 | public void setup() { 8 | size(800, 300); 9 | frameRate(120); 10 | leap = new LeapMotionP5(this); 11 | values = new LinkedList(); 12 | stroke(255); 13 | } 14 | 15 | int lastY = 0; 16 | 17 | public void draw() { 18 | translate(0, 180); 19 | background(0); 20 | if (values.size() >= width) { 21 | values.removeFirst(); 22 | } 23 | 24 | values.add((int) leap.getVelocity(leap.getHand(0)).y); 25 | //System.out.println((int) leap.getVelocity(leap.getHand(0)).y); 26 | int counter = 0; 27 | for (Integer val : values) { 28 | val = (int) map(val, 0, 1500, 0, height); 29 | line(counter, val, counter - 1, lastY); 30 | point(counter, val); 31 | lastY = val; 32 | counter++; 33 | } 34 | 35 | line(0, map(1300, 0, 1500, 0, height), width, map(1300, 0, 1500, 0, height)); 36 | } 37 | 38 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | # UTF-8 supported. 2 | 3 | # The name of your library as you want it formatted 4 | name = LeapMotionP5 5 | 6 | # List of authors. Links can be provided using the syntax [author name](url) 7 | authorList = [Marcel Schwittlick] (https://github.com/mrzl) [onformative](http://www.onformative.com/) 8 | 9 | # A web page for your library, NOT a direct link to where to download it 10 | url = http://www.onformative.com/lab/leapmotionp5 11 | 12 | # The category of your library, must be one (or many) of the following: 13 | # "3D" "Animation" "Compilations" "Data" 14 | # "Fabrication" "Geometry" "GUI" "Hardware" 15 | # "I/O" "Language" "Math" "Simulation" 16 | # "Sound" "Utilities" "Typography" "Video & Vision" 17 | # 18 | # If a value other than those listed is used, your library will listed as "Other." 19 | category = Hardware 20 | 21 | # A short sentence (or fragment) to summarize the library's function. This will be 22 | # shown from inside the PDE when the library is being installed. Avoid repeating 23 | # the name of your library here. Also, avoid saying anything redundant like 24 | # mentioning that its a library. This should start with a capitalized letter, and 25 | # end with a period. 26 | sentence = Easy access library for the Leap Motion controller 27 | 28 | # Additional information suitable for the Processing website. The value of 29 | # 'sentence' always will be prepended, so you should start by writing the 30 | # second sentence here. If your library only works on certain operating systems, 31 | # mention it here. 32 | paragraph = 33 | 34 | # Links in the 'sentence' and 'paragraph' attributes can be inserted using the 35 | # same syntax as for authors. That is, [here is a link to Processing](http://processing.org/) 36 | 37 | 38 | # A version number that increments once with each release. This 39 | # is used to compare different versions of the same library, and 40 | # check if an update is available. You should think of it as a 41 | # counter, counting the total number of releases you've had. 42 | version = 1 # This must be parsable as an int 43 | 44 | # The version as the user will see it. If blank, the version attribute will be used here 45 | prettyVersion = 0.5b # This is treated as a String -------------------------------------------------------------------------------- /library/LeapJava.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onformative/LeapMotionP5/70d2926806a62462039073af565160b8a634df7e/library/LeapJava.jar -------------------------------------------------------------------------------- /library/LeapMotionP5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onformative/LeapMotionP5/70d2926806a62462039073af565160b8a634df7e/library/LeapMotionP5.jar -------------------------------------------------------------------------------- /library/macosx/libLeap.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onformative/LeapMotionP5/70d2926806a62462039073af565160b8a634df7e/library/macosx/libLeap.dylib -------------------------------------------------------------------------------- /library/macosx/libLeapJava.dylib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onformative/LeapMotionP5/70d2926806a62462039073af565160b8a634df7e/library/macosx/libLeapJava.dylib -------------------------------------------------------------------------------- /library/windows/Leap.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onformative/LeapMotionP5/70d2926806a62462039073af565160b8a634df7e/library/windows/Leap.dll -------------------------------------------------------------------------------- /library/windows/LeapJava.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onformative/LeapMotionP5/70d2926806a62462039073af565160b8a634df7e/library/windows/LeapJava.dll -------------------------------------------------------------------------------- /library/windows64/Leap.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onformative/LeapMotionP5/70d2926806a62462039073af565160b8a634df7e/library/windows64/Leap.dll -------------------------------------------------------------------------------- /library/windows64/LeapJava.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/onformative/LeapMotionP5/70d2926806a62462039073af565160b8a634df7e/library/windows64/LeapJava.dll -------------------------------------------------------------------------------- /src/com/onformative/leap/LeapMotionListener.java: -------------------------------------------------------------------------------- 1 | package com.onformative.leap; 2 | 3 | /** 4 | * LeapMotionP5 5 | * 6 | * LeapMotionP5 library for Processing. Copyright (c) 2012-2013 held jointly by the individual 7 | * authors. 8 | * 9 | * LeapMotionP5 library for Processing is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free Software Foundation, 11 | * either version 3 of the License, or (at your option) any later version. 12 | * 13 | * LeapMotionP5 for Processing is distributed in the hope that it will be useful, but WITHOUT ANY 14 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 15 | * PURPOSE. See the GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along with LeapMotionP5 library 18 | * for Processing. If not, see http://www.gnu.org/licenses/. 19 | * 20 | * Leap Developer SDK. Copyright (C) 2012-2013 Leap Motion, Inc. All rights reserved. 21 | * 22 | * NOTICE: This developer release of Leap Motion, Inc. software is confidential and intended for 23 | * very limited distribution. Parties using this software must accept the SDK Agreement prior to 24 | * obtaining this software and related tools. This software is subject to copyright. 25 | */ 26 | 27 | import java.util.Date; 28 | import java.util.LinkedList; 29 | import java.util.concurrent.ConcurrentSkipListMap; 30 | import java.util.concurrent.CopyOnWriteArrayList; 31 | 32 | import processing.core.PApplet; 33 | 34 | import com.leapmotion.leap.CircleGesture; 35 | import com.leapmotion.leap.Controller; 36 | import com.leapmotion.leap.Frame; 37 | import com.leapmotion.leap.Gesture; 38 | import com.leapmotion.leap.Gesture.State; 39 | import com.leapmotion.leap.GestureList; 40 | import com.leapmotion.leap.KeyTapGesture; 41 | import com.leapmotion.leap.Listener; 42 | import com.leapmotion.leap.ScreenTapGesture; 43 | import com.leapmotion.leap.SwipeGesture; 44 | 45 | /** 46 | * LeapMotionListener.java 47 | * 48 | * @author Marcel Schwittlick 49 | * @modified 04.02.2013 50 | * 51 | * this listener is listening for the events of the offical leap motion sdk 52 | */ 53 | class LeapMotionListener extends Listener { 54 | private LeapMotionP5 leap; 55 | 56 | protected int maxFramesToRecord = 1000; 57 | private String callbackMethodNameCircle; 58 | private String callbackMethodNameSwipe; 59 | private String callbackMethodNameScreenTap; 60 | private String callbackMethodNameKeyTap; 61 | 62 | /** 63 | * 64 | * @param p PApplet the processing applet 65 | * @param leap LeapMotionP5 an instance of the LeapMotionP5 class 66 | */ 67 | public LeapMotionListener(LeapMotionP5 leap) { 68 | this.leap = leap; 69 | this.leap.currentFrame = new Frame(); 70 | this.leap.lastFrames = new LinkedList(); 71 | this.leap.lastFramesInclProperTimestamps = new ConcurrentSkipListMap(); 72 | this.leap.oldFrames = new CopyOnWriteArrayList(); 73 | this.leap.oldControllers = new LinkedList(); 74 | 75 | this.callbackMethodNameCircle = "circleGestureRecognized"; 76 | this.callbackMethodNameSwipe = "swipeGestureRecognized"; 77 | this.callbackMethodNameScreenTap = "screenTapGestureRecognized"; 78 | this.callbackMethodNameKeyTap = "keyTapGestureRecognized"; 79 | } 80 | 81 | public void onInit(Controller controller) { 82 | System.out.println("Leap Motion Initialized"); 83 | } 84 | 85 | public void onConnect(Controller controller) { 86 | System.out.println("Leap Motion Connected"); 87 | } 88 | 89 | public void onDisconnect(Controller controller) { 90 | System.out.println("Leap Motion Disconnected"); 91 | } 92 | 93 | public void onExit(Controller controller) { 94 | System.out.println("Leap Motion Exited"); 95 | } 96 | 97 | private void invokeCallback(Gesture gesture) { 98 | PApplet parent = this.leap.getParent(); 99 | 100 | if (parent != null) { 101 | switch (gesture.type()) { 102 | case TYPE_CIRCLE: 103 | CircleGesture circleGesture = new CircleGesture(gesture); 104 | String clockwiseness; 105 | if (circleGesture.pointable().direction().angleTo(circleGesture.normal()) <= Math.PI / 4) { 106 | // Clockwise if angle is less than 90 degrees 107 | clockwiseness = "clockwise"; 108 | } else { 109 | clockwiseness = "counterclockwise"; 110 | } 111 | try { 112 | parent.getClass() 113 | .getMethod(this.callbackMethodNameCircle, CircleGesture.class, String.class) 114 | .invoke(parent, circleGesture, clockwiseness); 115 | } catch (Exception e) { 116 | PApplet.println(e.getMessage() + " CALLBACK ERROR"); 117 | } 118 | break; 119 | case TYPE_SWIPE: 120 | SwipeGesture swipeGesture = new SwipeGesture(gesture); 121 | try { 122 | parent.getClass().getMethod(this.callbackMethodNameSwipe, SwipeGesture.class) 123 | .invoke(parent, swipeGesture); 124 | } catch (Exception e) { 125 | PApplet.println(e.getMessage() + " CALLBACK ERROR"); 126 | } 127 | break; 128 | case TYPE_SCREEN_TAP: 129 | ScreenTapGesture screenTapGesture = new ScreenTapGesture(gesture); 130 | try { 131 | parent.getClass().getMethod(this.callbackMethodNameScreenTap, ScreenTapGesture.class) 132 | .invoke(parent, screenTapGesture); 133 | } catch (Exception e) { 134 | PApplet.println(e.getMessage() + " CALLBACK ERROR"); 135 | } 136 | break; 137 | case TYPE_KEY_TAP: 138 | KeyTapGesture keyTapGesture = new KeyTapGesture(gesture); 139 | try { 140 | parent.getClass().getMethod(this.callbackMethodNameKeyTap, KeyTapGesture.class) 141 | .invoke(parent, keyTapGesture); 142 | } catch (Exception e) { 143 | PApplet.println(e.getMessage() + " CALLBACK ERROR"); 144 | } 145 | break; 146 | default: 147 | break; 148 | } 149 | } 150 | 151 | 152 | } 153 | 154 | private void printGestureDetails(Gesture gesture, Controller controller) { 155 | switch (gesture.type()) { 156 | case TYPE_CIRCLE: 157 | CircleGesture circle = new CircleGesture(gesture); 158 | 159 | // Calculate clock direction using the angle between circle normal and pointable 160 | String clockwiseness; 161 | if (circle.pointable().direction().angleTo(circle.normal()) <= Math.PI / 4) { 162 | // Clockwise if angle is less than 90 degrees 163 | clockwiseness = "clockwise"; 164 | } else { 165 | clockwiseness = "counterclockwise"; 166 | } 167 | 168 | // Calculate angle swept since last frame 169 | double sweptAngle = 0; 170 | if (circle.state() != State.STATE_START) { 171 | CircleGesture previousUpdate = 172 | new CircleGesture(controller.frame(1).gesture(circle.id())); 173 | sweptAngle = (circle.progress() - previousUpdate.progress()) * 2 * Math.PI; 174 | } 175 | 176 | System.out.println("Circle id: " + circle.id() + ", " + circle.state() + ", progress: " 177 | + circle.progress() + ", radius: " + circle.radius() + ", angle: " 178 | + Math.toDegrees(sweptAngle) + ", " + clockwiseness); 179 | break; 180 | case TYPE_SWIPE: 181 | SwipeGesture swipe = new SwipeGesture(gesture); 182 | System.out.println("Swipe id: " + swipe.id() + ", " + swipe.state() + ", position: " 183 | + swipe.position() + ", direction: " + swipe.direction() + ", speed: " + swipe.speed()); 184 | break; 185 | case TYPE_SCREEN_TAP: 186 | ScreenTapGesture screenTap = new ScreenTapGesture(gesture); 187 | System.out.println("Screen Tap id: " + screenTap.id() + ", " + screenTap.state() 188 | + ", position: " + screenTap.position() + ", direction: " + screenTap.direction()); 189 | break; 190 | case TYPE_KEY_TAP: 191 | KeyTapGesture keyTap = new KeyTapGesture(gesture); 192 | System.out.println("Key Tap id: " + keyTap.id() + ", " + keyTap.state() + ", position: " 193 | + keyTap.position() + ", direction: " + keyTap.direction()); 194 | break; 195 | default: 196 | System.out.println("Unknown gesture type."); 197 | break; 198 | } 199 | 200 | } 201 | 202 | private void processGestures(Controller controller) { 203 | GestureList list = controller.frame().gestures(); 204 | if (list.empty() == false) { 205 | for (int i = 0; i < list.count(); i++) { 206 | Gesture gesture = list.get(i); 207 | invokeCallback(gesture); 208 | // printGestureDetails(gesture, controller); 209 | } 210 | } 211 | } 212 | 213 | /** 214 | * this is called about 100-120 times a second delevering a new frame with information from the 215 | * leap tracking everything in its viewport. This is where most of the data which is accessible in 216 | * processing is coming from 217 | */ 218 | public void onFrame(Controller controller) { 219 | Frame frame = controller.frame(); 220 | this.leap.currentFrame = frame; 221 | 222 | processGestures(controller); 223 | 224 | // adding frames the list. making sure that only the newest frames are saved in order 225 | if (leap.lastFrames.size() >= maxFramesToRecord) { 226 | leap.lastFrames.removeFirst(); 227 | } 228 | leap.lastFrames.add(frame); 229 | 230 | // adding frames to the list. adding a proper timestamp to each frame object 231 | if (leap.lastFramesInclProperTimestamps.size() >= maxFramesToRecord) { 232 | leap.lastFramesInclProperTimestamps.remove(leap.lastFramesInclProperTimestamps.firstKey()); 233 | } 234 | leap.lastFramesInclProperTimestamps.put(new Date(), frame); 235 | 236 | // adding old frames to different object 237 | if (leap.oldFrames.size() >= maxFramesToRecord) { 238 | leap.oldFrames.remove(0); 239 | } 240 | leap.oldFrames.add(frame); 241 | 242 | if (leap.oldControllers.size() >= maxFramesToRecord) { 243 | leap.oldControllers.removeLast(); 244 | } 245 | leap.oldControllers.add(controller); 246 | } 247 | } 248 | -------------------------------------------------------------------------------- /src/com/onformative/leap/LeapMotionP5.java: -------------------------------------------------------------------------------- 1 | package com.onformative.leap; 2 | 3 | /** 4 | * LeapMotionP5 5 | * 6 | * LeapMotionP5 library for Processing. Copyright (c) 2012-2013 held jointly by the individual 7 | * authors. 8 | * 9 | * LeapMotionP5 library for Processing is free software: you can redistribute it and/or modify it 10 | * under the terms of the GNU General Public License as published by the Free Software Foundation, 11 | * either version 3 of the License, or (at your option) any later version. 12 | * 13 | * LeapMotionP5 for Processing is distributed in the hope that it will be useful, but WITHOUT ANY 14 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 15 | * PURPOSE. See the GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License along with LeapMotionP5 library 18 | * for Processing. If not, see http://www.gnu.org/licenses/. 19 | * 20 | * Leap Developer SDK. Copyright (C) 2012-2013 Leap Motion, Inc. All rights reserved. 21 | * 22 | * NOTICE: This developer release of Leap Motion, Inc. software is confidential and intended for 23 | * very limited distribution. Parties using this software must accept the SDK Agreement prior to 24 | * obtaining this software and related tools. This software is subject to copyright. 25 | */ 26 | 27 | import java.util.ArrayList; 28 | import java.util.Date; 29 | import java.util.HashMap; 30 | import java.util.Iterator; 31 | import java.util.LinkedList; 32 | import java.util.Map.Entry; 33 | import java.util.Set; 34 | import java.util.concurrent.ConcurrentSkipListMap; 35 | import java.util.concurrent.CopyOnWriteArrayList; 36 | 37 | import processing.core.PApplet; 38 | import processing.core.PVector; 39 | 40 | import com.leapmotion.leap.Config; 41 | import com.leapmotion.leap.Controller; 42 | import com.leapmotion.leap.Finger; 43 | import com.leapmotion.leap.Frame; 44 | import com.leapmotion.leap.Gesture.Type; 45 | import com.leapmotion.leap.Hand; 46 | import com.leapmotion.leap.Pointable; 47 | import com.leapmotion.leap.ScreenList; 48 | import com.leapmotion.leap.Tool; 49 | import com.leapmotion.leap.Vector; 50 | 51 | /** 52 | * LeapMotionP5.java 53 | * 54 | * @author Marcel Schwittlick 55 | * @modified 15.03.2013 56 | * 57 | */ 58 | public class LeapMotionP5 { 59 | private PApplet p; 60 | private LeapMotionListener listener; 61 | private Controller controller; 62 | private String sdkVersion = "0.7.7"; 63 | 64 | private final float LEAP_WIDTH = 200.0f; // in mm 65 | private final float LEAP_HEIGHT = 500.0f; // in mm 66 | private final float LEAP_DEPTH = 200.0f; // in mm 67 | 68 | protected Frame currentFrame; 69 | protected LinkedList lastFrames; 70 | protected CopyOnWriteArrayList oldFrames; 71 | protected LinkedList oldControllers; 72 | protected ConcurrentSkipListMap lastFramesInclProperTimestamps; 73 | 74 | protected HashMap lastDetectedFinger; 75 | protected HashMap lastDetectedPointable; 76 | protected HashMap lastDetectedHand; 77 | protected HashMap lastDetectedTool; 78 | 79 | private int activeScreenNr = 0; 80 | 81 | private Finger velocityOffsetTestFinger; 82 | 83 | /** 84 | * this class gives you some high level access to the data tracked and recorded by the leap. it 85 | * gives you a different way of access than the original leap sdk and transoforms all data into 86 | * processing equivalent datatypes. 87 | * 88 | * @param p PApplet the processing applet 89 | */ 90 | public LeapMotionP5(PApplet p) { 91 | this.p = p; 92 | 93 | this.listener = new LeapMotionListener(this); 94 | this.controller = new Controller(); 95 | 96 | this.controller.addListener(listener); 97 | 98 | this.lastDetectedFinger = new HashMap(); 99 | this.lastDetectedPointable = new HashMap(); 100 | this.lastDetectedHand = new HashMap(); 101 | this.lastDetectedTool = new HashMap(); 102 | 103 | this.lastDetectedFinger.put(0, new Finger()); 104 | this.lastDetectedPointable.put(0, new Pointable()); 105 | this.lastDetectedHand.put(0, new Hand()); 106 | this.lastDetectedTool.put(0, new Tool()); 107 | 108 | // this is neccessary because the velocity of all objects has an offset. 109 | this.velocityOffsetTestFinger = new Finger(); 110 | } 111 | 112 | /** 113 | * 114 | * @return 115 | */ 116 | public String getSDKVersion() { 117 | return this.sdkVersion; 118 | } 119 | 120 | /** 121 | * 122 | * @param max 123 | */ 124 | public void maxFramesToRecord(int max) { 125 | this.listener.maxFramesToRecord = max; 126 | } 127 | 128 | /** 129 | * this prints out the current offset of the vectors from the sdk. this is just for information 130 | * and will give you the position, velocity and acceleration offsets 131 | */ 132 | public void printCorrectionOffset() { 133 | System.out.println("pos offset: " + getTip(this.velocityOffsetTestFinger)); 134 | System.out.println("velo offset: " + getVelocity(this.velocityOffsetTestFinger)); 135 | System.out.println("acc offset: " + getAcceleration(this.velocityOffsetTestFinger)); 136 | } 137 | 138 | /** 139 | * 140 | */ 141 | public void stop() { 142 | this.controller.removeListener(this.listener); 143 | this.p.stop(); 144 | } 145 | 146 | /** 147 | * this returns a pvector containing the velocity offset. the problems the velocity offset has 148 | * with it, is that the velocity is slightly shiftet. for example if you shouldnt have any 149 | * velocity, because the finger is stanging still its returning a velocity that is initialized 150 | * with a new Finger object. this should be fixed with the upcoming sdk releases (i hope) * 151 | * 152 | * @return PVector containing the velocity offset 153 | */ 154 | public PVector velocityOffset() { 155 | return vectorToPVector(this.velocityOffsetTestFinger.tipVelocity()); 156 | } 157 | 158 | public PVector positionOffset() { 159 | return vectorToPVector(this.velocityOffsetTestFinger.tipPosition()); 160 | } 161 | 162 | /** 163 | * this retuns an pvector containing the acceleration offset, that has to be substracted from 164 | * every vector returned from the library. unfortunately the leap sdk has a little bug there. 165 | * 166 | * @return PVector containing the acceleration offset 167 | */ 168 | public PVector accelerationOffset() { 169 | return getAcceleration(this.velocityOffsetTestFinger); 170 | } 171 | 172 | public void enableGesture(Type gestureName) { 173 | this.controller.enableGesture(gestureName); 174 | } 175 | 176 | public void disableGesture(Type gesture) { 177 | this.controller.enableGesture(gesture, false); 178 | } 179 | 180 | public boolean isEnabled(Type gesture) { 181 | return this.controller.isGestureEnabled(gesture); 182 | } 183 | 184 | /** 185 | * this returns the parent applet of the library - the processing applet. 186 | * 187 | * @return PApplet parent 188 | */ 189 | public PApplet getParent() { 190 | return this.p; 191 | } 192 | 193 | /** 194 | * returns the controller of the leap sdk 195 | * 196 | * @return Controller controller 197 | */ 198 | public Controller getController() { 199 | try { 200 | return this.controller; 201 | } catch (Exception e) { 202 | System.err 203 | .println("Can not return controller not initialized. Returning new Controller object"); 204 | System.out.println(e); 205 | return new Controller(); 206 | } 207 | } 208 | 209 | /** 210 | * returns the most current frame from the leap sdk. a frame contains every tracked data from the 211 | * leap about your fingers. 212 | * 213 | * @return Frame the leap frame 214 | */ 215 | public Frame getFrame() { 216 | try { 217 | return this.currentFrame; 218 | } catch (Exception e) { 219 | System.err.println("Can not return current frame. Returning new Frame object instead"); 220 | System.err.println(e); 221 | return new Frame(); 222 | } 223 | } 224 | 225 | /** 226 | * returns a frame by id. 227 | * 228 | * @param id the id of the frame you want 229 | * @return Frame the frame which id you passed as a parameter. if the frame with the id you asked 230 | * for is not currently saved anymore you'll get a new Frame object. 231 | */ 232 | public Frame getFrame(int id) { 233 | Frame returnFrame = new Frame(); 234 | for (Frame frame : getFrames()) { 235 | if (frame.id() >= id) { 236 | returnFrame = frame; 237 | } 238 | } 239 | return returnFrame; 240 | } 241 | 242 | /** 243 | * returns the frame before the most current frame. 244 | * 245 | * @return 246 | */ 247 | public Frame getLastFrame() { 248 | return getFrames().get(getFrames().size() - 2); 249 | } 250 | 251 | public Controller getLastController() { 252 | return getLastControllers().get(getLastControllers().size() - 40); 253 | } 254 | 255 | /** 256 | * returns the frame that was before the frame you passed. 257 | * 258 | * @param frame 259 | * @return the frame that was recorded right before the frame you passed. 260 | */ 261 | public Frame getFrameBeforeFrame(Frame frame) { 262 | Frame frameBefore = null; 263 | 264 | for (Frame of : getFrames()) { 265 | if (of.id() == frame.id() - 1) { 266 | frameBefore = of; 267 | } 268 | } 269 | 270 | 271 | return frameBefore; 272 | } 273 | 274 | /** 275 | * returns a CopyOnWriteArrayList containing all recently buffered frames. 276 | * 277 | * @return a CopyOnWriteArrayList containing the newest elements 278 | */ 279 | public CopyOnWriteArrayList getFrames() { 280 | try { 281 | return this.oldFrames; 282 | } catch (Exception e) { 283 | System.err.println("Can not return list of last frames. Returning empty list instead."); 284 | System.err.println(e); 285 | return new CopyOnWriteArrayList(); 286 | } 287 | } 288 | 289 | public LinkedList getLastControllers() { 290 | return this.oldControllers; 291 | } 292 | 293 | /** 294 | * returns a linkedlist containing the last buffered frame 295 | * 296 | * @param frameCount the number of last frames 297 | * @return a list containing all last frames 298 | */ 299 | public LinkedList getFrames(int frameCount) { 300 | LinkedList frames = new LinkedList(); 301 | for (int i = 0; i < frameCount; i++) { 302 | if (getFrames().size() > frameCount) { 303 | Frame fr = getFrames().get(getFrames().size() - frameCount + i); 304 | frames.add(fr); 305 | } 306 | } 307 | return frames; 308 | } 309 | 310 | /** 311 | * 312 | * @return 313 | */ 314 | public PVector getFingerPositionXYPlane() { 315 | PVector fingerPositionXYPlane = new PVector(); 316 | 317 | Frame frame = getFrame(); 318 | if (frame.hands().isEmpty() == false) { 319 | Hand hand = frame.hands().get(0); 320 | if (hand.fingers().isEmpty() == false) { 321 | Finger finger = hand.fingers().get(0); 322 | fingerPositionXYPlane.x = transformLeapToScreenX(finger.tipPosition().getX()); 323 | fingerPositionXYPlane.y = transformLeapToScreenY(finger.tipPosition().getY()); 324 | } 325 | } 326 | 327 | return fingerPositionXYPlane; 328 | } 329 | 330 | /** 331 | * converts the x coordinate from the leap space into the processing window space 332 | * 333 | * @param x leap-space 334 | * @return processing-window space 335 | */ 336 | public float transformLeapToScreenX(float x) { 337 | /* 338 | * int startX = -243; int endX = 256; float valueMapped = PApplet.map(x, startX, endX, 0, 339 | * p.width); return valueMapped; 340 | */ 341 | float c = this.p.width / 2.0f; 342 | if (x > 0.0) { 343 | return PApplet.lerp(c, this.p.width, x / LEAP_WIDTH); 344 | } else { 345 | return PApplet.lerp(c, 0.0f, -x / LEAP_WIDTH); 346 | } 347 | } 348 | 349 | /** 350 | * converts the y coordinate from the leap space into the processing window space 351 | * 352 | * @param y leap space 353 | * @return processing-window space 354 | */ 355 | public float transformLeapToScreenY(float y) { 356 | /* 357 | * int startY = 50; int endY = 350; float valueMapped = PApplet.map(y, startY, endY, 0, 358 | * p.height); return valueMapped; 359 | */ 360 | return PApplet.lerp(this.p.height, 0.0f, y / LEAP_HEIGHT); 361 | } 362 | 363 | /** 364 | * converts the z coordinate from the leap space into the processing window space 365 | * 366 | * @param z leap space 367 | * @return processing window space 368 | */ 369 | public float transformLeapToScreenZ(float z) { 370 | /* 371 | * int startZ = -51; int endZ = 149; float valueMapped = PApplet.map(z, startZ, endZ, 0, 372 | * p.width); return valueMapped; 373 | */ 374 | return PApplet.lerp(0, this.p.width, z / LEAP_DEPTH); 375 | } 376 | 377 | /** 378 | * converts a vector from the leap space into the processing window space 379 | * 380 | * @param vector from the leap sdk containing a position in the leap space 381 | * @return the vector in PVector data type containing the same position in processing window space 382 | */ 383 | public PVector vectorToPVector(Vector vector) { 384 | return convertLeapToScreenDimension(vector.getX(), vector.getY(), vector.getZ()); 385 | } 386 | 387 | /** 388 | * converts x, y and z coordinates of the leap to the dimensions of your sketch 389 | * 390 | * @param x x position in leap world coordinate system 391 | * @param y y position in leap world coordinate system 392 | * @param z z position in leap world coordinate system 393 | * @return PVector the pvector of the point you passed in converted to the dimensions of your 394 | * processing sketch window 395 | */ 396 | public PVector convertLeapToScreenDimension(float x, float y, float z) { 397 | PVector positionRelativeToFrame = new PVector(); 398 | positionRelativeToFrame.x = transformLeapToScreenX(x); 399 | positionRelativeToFrame.y = transformLeapToScreenY(y); 400 | positionRelativeToFrame.z = transformLeapToScreenZ(z); 401 | return positionRelativeToFrame; 402 | } 403 | 404 | /** 405 | * returns an arraylist containing all currently tracked hands 406 | * 407 | * @return ArrayList an arraylist containing all currently tracked hands 408 | */ 409 | public ArrayList getHandList() { 410 | ArrayList hands = new ArrayList(); 411 | Frame frame = getFrame(); 412 | if (frame.hands().isEmpty() == false) { 413 | for (Hand hand : frame.hands()) { 414 | hands.add(hand); 415 | } 416 | } 417 | return hands; 418 | } 419 | 420 | /** 421 | * returns all hands tracked in the frame you passed 422 | * 423 | * @param frame the frame from which to find out all tracked hands 424 | * @return arraylist containing all hands from the passed frame 425 | */ 426 | public ArrayList getHandList(Frame frame) { 427 | ArrayList hands = new ArrayList(); 428 | try { 429 | if (frame.hands().isEmpty() == false) { 430 | for (Hand hand : frame.hands()) { 431 | if (hand.isValid()) { 432 | hands.add(hand); 433 | } 434 | } 435 | } 436 | } catch (Exception e) { 437 | // ignore 438 | } 439 | return hands; 440 | } 441 | 442 | /** 443 | * gets a hand by number. the number is indicated by the order the hand appeared in the leap. so 444 | * the first hand tracked has the nr 0 and the second one the number 1. once one hand of them two 445 | * leaves the leap the one hand left has the nr 0. this is implemented like that because the leap 446 | * is loosing track of the id's of hand to easily. 447 | * 448 | * @param handNr nr of the hand 449 | * @return 450 | */ 451 | public Hand getHand(int handNr) { 452 | Hand returnHand = null; 453 | if (!getHandList().isEmpty()) { 454 | this.lastDetectedHand.put(handNr, getHandList().get(handNr)); 455 | } 456 | // returnHand = lastDetectedHand.get(handNr); 457 | int downCounter = 0; 458 | while (returnHand == null) { 459 | returnHand = this.lastDetectedHand.get(handNr - downCounter); 460 | downCounter++; 461 | } 462 | return returnHand; 463 | } 464 | 465 | /** 466 | * returns a hand by id in the frame you passed. 467 | * 468 | * @param id 469 | * @param frame 470 | * @return 471 | */ 472 | public Hand getHandById(int id, Frame frame) { 473 | Hand returnHand = null; 474 | for (Hand hand : getHandList(frame)) { 475 | if (hand.id() == id) { 476 | returnHand = hand; 477 | } 478 | } 479 | return returnHand; 480 | } 481 | 482 | /** 483 | * 484 | * @return 485 | */ 486 | public float getScaleFactor() { 487 | return getFrame().scaleFactor(getLastFrame()); 488 | } 489 | 490 | /** 491 | * 492 | * @return 493 | */ 494 | public float getScaleFactor(Frame frame) { 495 | return getFrame().scaleFactor(frame); 496 | } 497 | 498 | /** 499 | * returns averaged translation of all points tracked by the leap in comparison to the last frame 500 | * 501 | * @return 502 | */ 503 | public PVector getTranslation() { 504 | PVector translation = vectorToPVector(getFrame().translation(getLastFrame())); 505 | translation.sub(velocityOffset()); 506 | return translation; 507 | } 508 | 509 | /** 510 | * returns averaged translation of all points tracked by the leap in comparison to the frame you 511 | * passed in the method 512 | * 513 | * @return 514 | */ 515 | public PVector getTranslation(Frame frame) { 516 | PVector translation = vectorToPVector(getFrame().translation(frame)); 517 | translation.sub(velocityOffset()); 518 | return translation; 519 | } 520 | 521 | /** 522 | * returns the pitch of the hand you passed 523 | * 524 | * @param hand the hand you want the pitch of 525 | * @return a float value containing the pitch of the hand 526 | */ 527 | public float getPitch(Hand hand) { 528 | // return PApplet.map((float) Math.toDegrees(hand.direction().pitch()), 0, 22, 0, 529 | // PConstants.TWO_PI); 530 | return (float) Math.toDegrees(hand.direction().pitch()); 531 | } 532 | 533 | /** 534 | * returns the roll of the hand you passed 535 | * 536 | * @param hand the hand you want the roll of 537 | * @return a float value containing the roll of the hand 538 | */ 539 | public float getRoll(Hand hand) { 540 | // return -PApplet.map((float) Math.toDegrees(hand.direction().roll()), 0, 180, 0, 541 | // PConstants.TWO_PI); 542 | return (float) Math.toDegrees(hand.palmNormal().roll()); 543 | } 544 | 545 | /** 546 | * returns the yaw of the hand you passed 547 | * 548 | * @param hand the hand you want the yaw of 549 | * @return a float value containing the yaw of the hand 550 | */ 551 | public float getYaw(Hand hand) { 552 | return (float) Math.toDegrees(hand.direction().yaw()); 553 | } 554 | 555 | /** 556 | * returns a PVector containing the direction of the hand 557 | * 558 | * @param hand the hand you want the direction of 559 | * @return PVector direction of the hand 560 | */ 561 | public PVector getDirection(Hand hand) { 562 | 563 | PVector dir = vectorToPVector(hand.direction()); 564 | dir.sub(positionOffset()); 565 | return dir; 566 | } 567 | 568 | /** 569 | * returns a PVector containing the position of the hand 570 | * 571 | * @param hand the hand you want the position of 572 | * @return PVector position of the hand 573 | */ 574 | public PVector getPosition(Hand hand) { 575 | return vectorToPVector(hand.palmPosition()); 576 | } 577 | 578 | /** 579 | * retrusn the normal of the palm of the hand 580 | * 581 | * @param hand the hand you want the normal of the handpalm of 582 | * @return a PVector containing the normal of thepalm of the hand 583 | */ 584 | public PVector getNormal(Hand hand) { 585 | PVector normal = vectorToPVector(hand.palmNormal()); 586 | normal.sub(positionOffset()); 587 | return normal; 588 | } 589 | 590 | /** 591 | * returns the velocity of the palm of the hand you passed in 592 | * 593 | * @param hand the hand of which palm you want the velocity of 594 | * @return a PVector containing the velocity of the hand 595 | */ 596 | public PVector getVelocity(Hand hand) { 597 | PVector velo = vectorToPVector(hand.palmVelocity()); 598 | velo.sub(velocityOffset()); 599 | return velo; 600 | } 601 | 602 | /** 603 | * access to the acceleration of the hand you passed in. 604 | * 605 | * @param hand the hand you want the acceleration of 606 | * @return a PVector containing the acceleration of the hand you passed in 607 | */ 608 | public PVector getAcceleration(Hand hand) { 609 | PVector acceleration = null; 610 | 611 | Frame currentFrame = getFrame(); 612 | Frame lastFrame = getFrameBeforeFrame(currentFrame); 613 | PVector currentVelo = new PVector(); 614 | PVector lastVelo = new PVector(); 615 | try { 616 | currentVelo = getVelocity(hand); 617 | lastVelo = getVelocity(getHandById(hand.id(), lastFrame)); 618 | } catch (Exception e) { 619 | // ignore 620 | } 621 | currentVelo.sub(lastVelo); 622 | currentVelo.div(2); 623 | acceleration = currentVelo; 624 | 625 | return acceleration; 626 | } 627 | 628 | /** 629 | * 630 | * @param hand 631 | * @return 632 | */ 633 | public PVector getSphereCenter(Hand hand) { 634 | return vectorToPVector(hand.sphereCenter()); 635 | } 636 | 637 | /** 638 | * 639 | * @param hand 640 | * @return 641 | */ 642 | public float getSphereRadius(Hand hand) { 643 | return hand.sphereRadius(); 644 | } 645 | 646 | /** 647 | * access to all fingers that are currently tracked 648 | * 649 | * @return ArrayList an arraylist containing all currently tracked fingers 650 | */ 651 | public ArrayList getFingerList() { 652 | ArrayList fingers = new ArrayList(); 653 | 654 | Frame frame = getFrame(); 655 | if (frame.hands().isEmpty() == false) { 656 | for (Hand hand : frame.hands()) { 657 | fingers.addAll(getFingerList(hand)); 658 | } 659 | } 660 | 661 | return fingers; 662 | } 663 | 664 | /** 665 | * access to all tracked fingers in the frame you passed in 666 | * 667 | * @param frame the frame you want all tracked fingers of 668 | * @return an arraylist containing all tracked fingers 669 | */ 670 | public ArrayList getFingerList(Frame frame) { 671 | ArrayList fingers = new ArrayList(); 672 | 673 | if (frame.hands().isEmpty() == false) { 674 | for (Hand hand : frame.hands()) { 675 | fingers.addAll(getFingerList(hand)); 676 | } 677 | } 678 | 679 | return fingers; 680 | } 681 | 682 | /** 683 | * access to all fingers of the hand you passed in 684 | * 685 | * @param hand the hand you want all tracked fingers of 686 | * @return an arraylist containing all tracked fingers of the hand 687 | */ 688 | public ArrayList getFingerList(Hand hand) { 689 | ArrayList fingers = new ArrayList(); 690 | 691 | for (Finger finger : hand.fingers()) { 692 | fingers.add(finger); 693 | } 694 | return fingers; 695 | } 696 | 697 | /** 698 | * returns the finger by number. the fingers are numbered by the occurence in the leap. 699 | * 700 | * @param fingerNr 701 | * @return 702 | */ 703 | public Finger getFinger(int fingerNr) { 704 | Finger returnFinger = null; 705 | if (getFingerList().size() > fingerNr) { 706 | this.lastDetectedFinger.put(fingerNr, getFingerList().get(fingerNr)); 707 | } 708 | // returnFinger = lastDetectedFinger.get(fingerNr); 709 | int downCounter = 0; 710 | while (returnFinger == null) { 711 | returnFinger = this.lastDetectedFinger.get(fingerNr - downCounter); 712 | downCounter++; 713 | } 714 | return returnFinger; 715 | } 716 | 717 | /** 718 | * 719 | * @param id 720 | * @param frame 721 | * @return 722 | */ 723 | public Finger getFingerById(int id, Frame frame) { 724 | Finger returnFinger = null; 725 | for (Finger finger : getFingerList(frame)) { 726 | if (finger.id() == id) { 727 | returnFinger = finger; 728 | } 729 | } 730 | return returnFinger; 731 | } 732 | 733 | /** 734 | * returns the tip position of the passed pointable 735 | * 736 | * @param pointable the pointable you want the tippoisition of 737 | * @return a PVector containing the position of the tip of the pointable 738 | */ 739 | public PVector getTip(Pointable pointable) { 740 | return convertLeapToScreenDimension(pointable.tipPosition().getX(), pointable.tipPosition() 741 | .getY(), pointable.tipPosition().getZ()); 742 | } 743 | 744 | /** 745 | * sets the current screen for gettings the calibrated points. I should rewrite this, but nobody 746 | * is gonna read it anyway. arr. 747 | * 748 | * @param screenNr 749 | */ 750 | public void setActiveScreen(int screenNr) { 751 | this.activeScreenNr = screenNr; 752 | } 753 | 754 | /** 755 | * to use this utility you have to have the leap calirated to your screen 756 | * 757 | * @param pointable the finger you want the intersection with your screen from 758 | * @param screenNr the number of the screen you calibrated 759 | * @return 760 | */ 761 | public PVector getTipOnScreen(Pointable pointable) { 762 | PVector pos; 763 | 764 | ScreenList sl = this.controller.locatedScreens(); 765 | com.leapmotion.leap.Screen calibratedScreen = sl.get(activeScreenNr); 766 | Vector loc = calibratedScreen.intersect(pointable, true); 767 | 768 | float _x = PApplet.map(loc.getX(), 0, 1, 0, this.p.displayWidth); 769 | _x -= p.getLocationOnScreen().x; 770 | float _y = PApplet.map(loc.getY(), 0, 1, this.p.displayHeight, 0); 771 | _y -= p.getLocationOnScreen().y; 772 | 773 | pos = new PVector(_x, _y); 774 | return pos; 775 | } 776 | 777 | /** 778 | * returns the velocity of a finger on the screen 779 | * 780 | * @param pointable 781 | * @return 782 | */ 783 | 784 | public PVector getVelocityOnScreen(Pointable pointable) { 785 | Vector loc = new Vector(); 786 | Vector oldLoc = new Vector(); 787 | try { 788 | oldLoc = 789 | getLastController().locatedScreens().get(this.activeScreenNr) 790 | .intersect(getPointableById(pointable.id(), getLastFrame()), true); 791 | loc = this.controller.locatedScreens().get(this.activeScreenNr).intersect(pointable, true); 792 | } catch (NullPointerException e) { 793 | // dirty dirty hack to keep the programm runing. i like it. 794 | } 795 | 796 | float _x = PApplet.map(loc.getX(), 0, 1, 0, this.p.displayWidth); 797 | _x -= this.p.getLocationOnScreen().x; 798 | float _y = PApplet.map(loc.getY(), 0, 1, this.p.displayHeight, 0); 799 | _y -= this.p.getLocationOnScreen().y; 800 | 801 | float _x2 = PApplet.map(oldLoc.getX(), 0, 1, 0, this.p.displayWidth); 802 | _x2 -= this.p.getLocationOnScreen().x; 803 | float _y2 = PApplet.map(oldLoc.getY(), 0, 1, this.p.displayHeight, 0); 804 | _y2 -= this.p.getLocationOnScreen().y; 805 | 806 | return new PVector(_x - _x2, _y - _y2); 807 | } 808 | 809 | /** 810 | * returns the origin of the pointable. the origin is the place where the pointable leaves the 811 | * body of the hand. 812 | * 813 | * @param pointable the pointable you want the origin of 814 | * @return a PVector containing the position of the origin of the passed pointable 815 | */ 816 | public PVector getOrigin(Pointable pointable) { 817 | Vector anklePos; 818 | 819 | float length = pointable.length(); 820 | PVector direction = new PVector(); 821 | direction.x = pointable.direction().getX(); 822 | direction.y = pointable.direction().getY(); 823 | direction.z = pointable.direction().getZ(); 824 | direction.mult(length); 825 | anklePos = 826 | new Vector(pointable.tipPosition().getX() - direction.x, pointable.tipPosition().getY() 827 | - direction.y, pointable.tipPosition().getZ() - direction.z); 828 | 829 | return vectorToPVector(anklePos); 830 | } 831 | 832 | /** 833 | * returns the velocity of the pointbale 834 | * 835 | * @param pointable the pointable you want the velocity of 836 | * @return a PVector containing the velocity of the tip of the pointble 837 | */ 838 | public PVector getVelocity(Pointable pointable) { 839 | PVector velo = vectorToPVector(pointable.tipVelocity()); 840 | velo.sub(velocityOffset()); 841 | return velo; 842 | } 843 | 844 | 845 | 846 | /** 847 | * calculates the direction of the passed pointable 848 | * 849 | * @param pointable the pointable you want the direction of 850 | * @return a PVector containing the direction of the pointable 851 | */ 852 | public PVector getDirection(Pointable pointable) { 853 | return vectorToPVector(pointable.direction()); 854 | } 855 | 856 | /** 857 | * passes the length of a pointable though. 858 | * 859 | * @param pointable 860 | * @return 861 | */ 862 | public float getLength(Pointable pointable) { 863 | return pointable.length(); 864 | } 865 | 866 | /** 867 | * passes the width of a pointable through 868 | * 869 | * @param pointable 870 | * @return 871 | */ 872 | public float getWidth(Pointable pointable) { 873 | return pointable.width(); 874 | } 875 | 876 | /** 877 | * calculates the acceleration of the pointable according to the velocity of the curent and the 878 | * last frame 879 | * 880 | * @param pointable the pointable you want the acceleration of 881 | * @return a PVector containing the acceleration of the tip of the passed pointable 882 | */ 883 | public PVector getAcceleration(Pointable pointable) { 884 | 885 | PVector acceleration = null; 886 | 887 | Frame currentFrame = getFrame(); 888 | Frame lastFrame = getFrameBeforeFrame(currentFrame); 889 | PVector currentVelo = new PVector(); 890 | PVector lastVelo = new PVector(); 891 | try { 892 | currentVelo = getVelocity(pointable); 893 | lastVelo = getVelocity(getPointableById(pointable.id(), lastFrame)); 894 | } catch (Exception e) { 895 | // ignore 896 | } 897 | currentVelo.sub(lastVelo); 898 | currentVelo.div(2); 899 | acceleration = currentVelo; 900 | 901 | return acceleration; 902 | } 903 | 904 | /** 905 | * returns all pointables in the current frame 906 | * 907 | * @return ArrayList an arraylist containing all currently tracked pointables 908 | */ 909 | public ArrayList getPointableList() { 910 | ArrayList pointables = new ArrayList(); 911 | 912 | Frame frame = getFrame(); 913 | if (frame.hands().isEmpty() == false) { 914 | for (Hand hand : frame.hands()) { 915 | pointables.addAll(getPointableList(hand)); 916 | } 917 | } 918 | 919 | return pointables; 920 | } 921 | 922 | /** 923 | * returns all pointables of the passed framre 924 | * 925 | * @return ArrayList an arraylist containing all currently tracked pointables 926 | */ 927 | public ArrayList getPointableList(Frame frame) { 928 | ArrayList pointables = new ArrayList(); 929 | 930 | if (frame.hands().isEmpty() == false) { 931 | for (Hand hand : frame.hands()) { 932 | pointables.addAll(getPointableList(hand)); 933 | } 934 | } 935 | 936 | return pointables; 937 | } 938 | 939 | /** 940 | * returns all pointables of the passed hand 941 | * 942 | * @param hand the hand you want the pointables of 943 | * @return an arraylist containing the pointables of the passed hand 944 | */ 945 | public ArrayList getPointableList(Hand hand) { 946 | ArrayList pointables = new ArrayList(); 947 | 948 | for (Pointable pointable : hand.pointables()) { 949 | pointables.add(pointable); 950 | } 951 | 952 | return pointables; 953 | } 954 | 955 | /** 956 | * returns a pointable by its number. look up to the equivalent methods for hand/finger for 957 | * documentation 958 | * 959 | * @param pointableNr the number of the pointable 960 | * @return 961 | */ 962 | public Pointable getPointable(int pointableNr) { 963 | Pointable returnPointable = null; 964 | if (!getPointableList().isEmpty()) { 965 | this.lastDetectedPointable.put(pointableNr, getPointableList().get(pointableNr)); 966 | } 967 | // returnPointable = lastDetectedPointable.get(pointableNr); 968 | int downCounter = 0; 969 | while (returnPointable == null) { 970 | returnPointable = this.lastDetectedPointable.get(pointableNr - downCounter); 971 | downCounter++; 972 | } 973 | return returnPointable; 974 | } 975 | 976 | /** 977 | * returns a pointable by id in the passed frame 978 | * 979 | * @param id the if of the pointbale 980 | * @param frame the frame where to look for the pointable 981 | * @return 982 | */ 983 | public Pointable getPointableById(int id, Frame frame) { 984 | Pointable returnPointable = null; 985 | for (Pointable pointable : getPointableList(frame)) { 986 | if (pointable.id() == id) { 987 | returnPointable = pointable; 988 | } 989 | } 990 | return returnPointable; 991 | } 992 | 993 | /** 994 | * calculates an arraylist containing all tools in the current frame 995 | * 996 | * @return 997 | */ 998 | public ArrayList getToolList() { 999 | ArrayList tools = new ArrayList(); 1000 | 1001 | Frame frame = getFrame(); 1002 | if (frame.hands().isEmpty() == false) { 1003 | for (Hand hand : frame.hands()) { 1004 | tools.addAll(getToolList(hand)); 1005 | } 1006 | } 1007 | 1008 | return tools; 1009 | } 1010 | 1011 | /** 1012 | * calculates an arraylist containing all tools in the passed frame 1013 | * 1014 | * @return 1015 | */ 1016 | public ArrayList getToolList(Frame frame) { 1017 | ArrayList tools = new ArrayList(); 1018 | 1019 | if (frame.hands().isEmpty() == false) { 1020 | for (Hand hand : frame.hands()) { 1021 | tools.addAll(getToolList(hand)); 1022 | } 1023 | } 1024 | 1025 | return tools; 1026 | } 1027 | 1028 | /** 1029 | * returns a arraylist of tools attached to the passed hand 1030 | * 1031 | * @param hand 1032 | * @return 1033 | */ 1034 | public ArrayList getToolList(Hand hand) { 1035 | ArrayList tools = new ArrayList(); 1036 | 1037 | for (Tool tool : hand.tools()) { 1038 | tools.add(tool); 1039 | } 1040 | 1041 | return tools; 1042 | } 1043 | 1044 | /** 1045 | * returns a tool by its number 1046 | * 1047 | * @param toolNr 1048 | * @return 1049 | */ 1050 | public Tool getTool(int toolNr) { 1051 | Tool returnTool = null; 1052 | if (!getToolList().isEmpty()) { 1053 | this.lastDetectedTool.put(toolNr, getToolList().get(toolNr)); 1054 | } 1055 | // returnTool = lastDetectedTool.get(toolNr); 1056 | int downCounter = 0; 1057 | while (returnTool == null) { 1058 | returnTool = this.lastDetectedTool.get(toolNr - downCounter); 1059 | downCounter++; 1060 | } 1061 | return returnTool; 1062 | } 1063 | 1064 | /** 1065 | * calculates a proper timestamp of the passed frame 1066 | * 1067 | * @param frame the frame you want the timestamp of 1068 | * @return Date containing the timestamp when the frame was taken 1069 | */ 1070 | public Date getTimestamp(Frame frame) { 1071 | Date date = null; 1072 | Set> lastFramesInclDates = this.lastFramesInclProperTimestamps.entrySet(); 1073 | Iterator> i = lastFramesInclDates.iterator(); 1074 | while (i.hasNext()) { 1075 | Entry entry = i.next(); 1076 | String stringOfTimestampInMap = entry.getValue().timestamp() + ""; 1077 | String stringOfTimestampPassedParameter = frame.timestamp() + ""; 1078 | if (stringOfTimestampInMap.equals(stringOfTimestampPassedParameter)) { 1079 | date = entry.getKey(); 1080 | } 1081 | } 1082 | return date; 1083 | } 1084 | } 1085 | --------------------------------------------------------------------------------