Package com.onformative.leap

Source Code of com.onformative.leap.LeapMotionP5

package com.onformative.leap;

/**
* 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.
*
* NOTICE: This developer release of Leap Motion, Inc. software is confidential and intended for
* very limited distribution. Parties using this software must accept the SDK Agreement prior to
* obtaining this software and related tools. This software is subject to copyright.
*/

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 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 String sdkVersion = "0.8.1";

  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.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 -= p.getLocationOnScreen().x;
    float _y = PApplet.map(loc.getY(), 0, 1, this.p.displayHeight, 0);
    _y -= p.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.p.getLocationOnScreen().x;
    float _y = PApplet.map(loc.getY(), 0, 1, this.p.displayHeight, 0);
    _y -= this.p.getLocationOnScreen().y;

    float _x2 = PApplet.map(oldLoc.getX(), 0, 1, 0, this.p.displayWidth);
    _x2 -= this.p.getLocationOnScreen().x;
    float _y2 = PApplet.map(oldLoc.getY(), 0, 1, this.p.displayHeight, 0);
    _y2 -= this.p.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
   */
  public ArrayList<Tool> getToolList() {
    ArrayList<Tool> tools = new ArrayList<Tool>();

    Frame frame = getFrame();
    if (frame.hands().isEmpty() == false) {
      for (Hand hand : frame.hands()) {
        tools.addAll(getToolList(hand));
      }
    }

    return tools;
  }

  /**
   * calculates an arraylist containing all tools in the passed frame
   *
   * @return
   */
  public ArrayList<Tool> getToolList(Frame frame) {
    ArrayList<Tool> tools = new ArrayList<Tool>();

    if (frame.hands().isEmpty() == false) {
      for (Hand hand : frame.hands()) {
        tools.addAll(getToolList(hand));
      }
    }

    return tools;
  }

  /**
   * returns a arraylist of tools attached to the passed hand
   *
   * @param hand
   * @return
   */
  public ArrayList<Tool> getToolList(Hand hand) {
    ArrayList<Tool> tools = new ArrayList<Tool>();

    for (Tool tool : hand.tools()) {
      tools.add(tool);
    }

    return tools;
  }

  /**
   * returns a tool by its number
   *
   * @param toolNr
   * @return
   */
  public Tool getTool(int toolNr) {
    Tool returnTool = null;
    if (!getToolList().isEmpty()) {
      this.lastDetectedTool.put(toolNr, getToolList().get(toolNr));
    }
    // returnTool = lastDetectedTool.get(toolNr);
    int downCounter = 0;
    while (returnTool == null) {
      returnTool = this.lastDetectedTool.get(toolNr - downCounter);
      downCounter++;
    }
    return returnTool;
  }

  /**
   * calculates a proper timestamp of the passed frame
   *
   * @param frame the frame you want the timestamp of
   * @return Date containing the timestamp when the frame was taken
   */
  public Date getTimestamp(Frame frame) {
    Date date = null;
    Set<Entry<Date, Frame>> lastFramesInclDates = this.lastFramesInclProperTimestamps.entrySet();
    Iterator<Entry<Date, Frame>> i = lastFramesInclDates.iterator();
    while (i.hasNext()) {
      Entry<Date, Frame> entry = i.next();
      String stringOfTimestampInMap = entry.getValue().timestamp() + "";
      String stringOfTimestampPassedParameter = frame.timestamp() + "";
      if (stringOfTimestampInMap.equals(stringOfTimestampPassedParameter)) {
        date = entry.getKey();
      }
    }
    return date;
  }
}
TOP

Related Classes of com.onformative.leap.LeapMotionP5

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.