package org.squidy.nodes; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlType; import org.squidy.manager.controls.TextField; import org.squidy.manager.data.IData; import org.squidy.manager.data.Processor; import org.squidy.manager.data.Property; import org.squidy.manager.data.Processor.Status; import org.squidy.manager.data.impl.DataPosition2D; import org.squidy.manager.data.impl.DataPosition6D; import org.squidy.manager.model.AbstractNode; /** * <code>Intercept Display</code> * * @author Stephanie Foehrenbach * Workaround until OptiTrack Coordinate System can be placed in bottom * right corner of Cubes (currently not possible due to lack of hardware, * otherwise use interceptDisplay and change the width/height adjustable of the * OptiTrack Tracking Node) * * @version $Id: InterceptCubes.java 772 2011-09-16 15:39:44Z raedle $ * @since 1.5.0 */ @XmlType(name = "InterceptCubs") @Processor( name = "Intercept Cubes", tags = { "cubes", "intercept", "display", "6dof" }, types = { Processor.Type.FILTER }, status = Status.UNSTABLE ) public class InterceptCubes extends AbstractNode { // ################################################################################ // BEGIN OF ADJUSTABLES // ################################################################################ @XmlAttribute(name = "left-down-x") @Property( name = "Left down X", description = "Left down x-value of cubes in relation to OptiTrack Coordinate System in mm." ) @TextField private float leftDownX = 1000; /** * @return the leftDownX */ public final float getLeftDownX() { return leftDownX; } /** * @param width the leftDownX to set */ public final void setLeftDownX(float leftDownX) { this.leftDownX = leftDownX; } @XmlAttribute(name = "left-down-y") @Property( name = "Left down Y", description = "Left down y-value of cubes in relation to OptiTrack Coordinate System in mm." ) @TextField private float leftDownY = 1200; /** * @return the leftDownX */ public final float getLeftDownY() { return leftDownY; } /** * @param width the leftDownY to set */ public final void setLeftDownY(float leftDownY) { this.leftDownY = leftDownY; } @XmlAttribute(name = "left-down-z") @Property( name = "Left down Z", description = "Left down Z-value of cubes in relation to OptiTrack Coordinate System in mm." ) @TextField private float leftDownZ = -60; /** * @return the leftDownZ */ public final float getLeftDownZ() { return leftDownZ; } /** * @param width the leftDownZ to set */ public final void setLeftDownZ(float leftDownZ) { this.leftDownZ = leftDownZ; } // ################################################################################ // END OF ADJUSTABLES // ################################################################################ private double a1, a2, a3, ba1, ba2, ba3, d, x, y; /** * {@inheritDoc} */ public synchronized IData process(DataPosition6D dataPosition6D) { // Target position a1 = dataPosition6D.getX(); a2 = dataPosition6D.getY(); a3 = dataPosition6D.getZ(); // Point (0,0,z) is rotated using the rotation matrix of the target // by using (0,0,<any value>) the result can be used imidiatly as a // direction vector // direction vector ba1 = dataPosition6D.getM02() * dataPosition6D.getZ(); ba2 = dataPosition6D.getM12() * dataPosition6D.getZ(); ba3 = dataPosition6D.getM22() * dataPosition6D.getZ(); // This is a shortcut for: // // 1. rotate Point b=(0,0,1) using the rotation matrix of the Target // giving point b1 // Rotation Matrix * b // 2. translate b1 using the target position a1 // // b1 = pos6d.rxz * pos6d.z + pos6d.x; // b2 = pos6d.ryz * pos6d.z + pos6d.y; // b3 = pos6d.rzz * pos6d.z + pos6d.z; // // 3. use b1 and a1 to calculate the direction vector that // intersects // both points // ba1 = b1 - a1; // ba2 = b2 - a2; // ba3 = b3 - a3; // interception directection vector with x-y-plane d = (-1) * (a3 / ba3); x = a1 + d * ba1; y = a2 + d * ba2; // Workaround: simulate, that cubes are positioned at the optiTrack origin x = x - leftDownX; y = y - leftDownY; // switch x Value x = x * (-1); // normalise x, y as it is expected for 2D Objects // @ TODO: user dataPosition6D maxX attributs to normalize //x = norm(x, dataPosition6D.maxX); //y = norm(y, dataPosition6D.maxY); if(x==-1||y==-1) return null; return new DataPosition2D(InterceptCubes.class, x, y); } // private double norm(double val, double bound) { // double tmp = val / bound; // tmp = (tmp > 1.0) ? 1.0 : tmp; // tmp = (tmp < 0.0) ? 0.0 : tmp; // return tmp; // } private double norm(double val, double bound) { double tmp = val / bound; tmp = (tmp > 1.0) ? -1.0 : tmp; tmp = (tmp < 0.0) ? -1.0 : tmp; return tmp; } }