/**
* Copyright (C) 2013 Colorado School of Mines
*
* This file is part of the Interface Software Development Kit (SDK).
*
* The InterfaceSDK 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.
*
* The InterfaceSDK 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 the InterfaceSDK. If not, see <http://www.gnu.org/licenses/>.
*/
package edu.mines.acmX.exhibit.stdlib.input_processing.tracking;
import org.OpenNI.DepthGenerator;
import org.OpenNI.Point3D;
import org.OpenNI.StatusException;
import edu.mines.acmX.exhibit.stdlib.graphics.Coordinate3D;
public class HandTrackingUtilities {
/**
* Converts a Point3D provided by OpenNI to use a generic Coordinate3D.O
* @param gen OpenNI DepthGenerator
* @param point OpenNI Point3D for the given hand
* @return a POJO Coordinate3D
*
* @see {@link Coordinate3D}
*/
public static Coordinate3D convertOpenNIPoint(DepthGenerator gen, Point3D point) {
Point3D convertedPoint = null;
Coordinate3D ret = null;
try {
convertedPoint = gen.convertRealWorldToProjective(point);
ret = new Coordinate3D(convertedPoint.getX(),
convertedPoint.getY(),
convertedPoint.getZ());
} catch (StatusException e) {
e.printStackTrace();
}
return ret;
}
/**
* Scales a given hand coordinate to fill the user frame, and zooms the sensitive area of
* the hand device.
*
* @param handX The unmodified hand position (float)
* @param depthWidth The width of the frame used by the depth sensor (int)
* @param frameWidth The width of the window to be converted to (int)
* @param marginFraction The fraction of the screen to trim from the edges (float)
* @return The scaled hand position (int)
*/
public static int getScaledHandX(float handX, int depthWidth, int frameWidth, float marginFraction) {
//if no scaling is desired, 0 or any negative number will calculate a flat ratio of screen sizes
if (marginFraction <= 0) return (int) (handX * (float) frameWidth/depthWidth);
// if the margin is greater than 1/2 (would give negative remaining size), return flat ratio
if (marginFraction > 0.5) return (int) (handX * (float) frameWidth/depthWidth);
//get margin size (fraction of total screen size)
float marginX = depthWidth * marginFraction;
//find remainder of depth image to zoom into
float scaledDepthWidth = depthWidth - 2 * marginX;
//translate coordinate to new zoomed frame, and then perform screen size ratio
int newX = (int) ((handX - marginX) * frameWidth/scaledDepthWidth);
//if the calculated value is outside of the bounds of [0, frameWidth], return closest valid value
if (newX < 0) return 0;
if (newX > frameWidth) return frameWidth;
return newX;
}
/**
* Scales a given hand coordinate to fill the user frame, and zooms the sensitive area of
* the hand device.
*
* @param handY The unmodified hand position (float)
* @param depthHeight The height of the frame used by the depth sensor (int)
* @param frameHeight The height of the window to be converted to (int)
* @param marginFraction The fraction of the screen to trim from the edges (float)
* @return The scaled hand position (int)
*/
public static int getScaledHandY(float handY, int depthHeight, int frameHeight, float marginFraction) {
//if no scaling is desired, 0 or any negative number will calculate a flat ratio of screen sizes
if (marginFraction <= 0) return (int) (handY * (float) frameHeight/depthHeight);
// if the margin is greater than 1/2 (would give negative remaining size), return flat ratio
if (marginFraction > 0.5) return (int) (handY * (float) frameHeight/depthHeight);
//get margin size (fraction of total screen size)
float marginY = depthHeight * marginFraction;
//find remainder of depth image to zoom into
float scaledDepthHeight = depthHeight - 2 * marginY;
//translate coordinate to new zoomed frame, and then perform screen size ratio
int newY = (int) ((handY - marginY) * frameHeight/scaledDepthHeight);
//if the calculated value is outside of the bounds of [0, frameHeight], return closest valid value
if (newY < 0) return 0;
if (newY > frameHeight) return frameHeight;
return newY;
}
}