/** * */ package org.squidy.nodes; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.annotation.XmlType; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; 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.model.AbstractNode; /** * <code>RotationMedian</code>. * * <pre> * Date: Dec 7, 2009 * Time: 12:16:54 PM * </pre> * * * @author * Roman R�dle * <a href="mailto:Roman.Raedle@uni-konstanz.de">Roman.Raedle@uni-konstanz.de</a> * Human-Computer Interaction Group * University of Konstanz * * @version $Id: RotationMedian.java 772 2011-09-16 15:39:44Z raedle $ * @since 1.0.0 * * TODO [RR]: Clear list if token has been lifted. */ @XmlType(name = "Rotation Median") @Processor( name = "Rotation Median", icon = "/org/squidy/nodes/image/48x48/rotationmedian.png", types = { Processor.Type.FILTER }, tags = { "reactivision", "fiducial", "id", "token", "rotation", "median" }, status = Status.UNSTABLE ) public class RotationMedian extends AbstractNode { // Log to log info, error, debug,... messages. private static final Log LOG = LogFactory.getLog(RotationMedian.class); // ################################################################################ // BEGIN OF ADJUSTABLES // ################################################################################ @Property( name = "History size", description = "Size of values kept as history values." ) @TextField private int historySize = 10; public int getHistorySize() { return historySize; } public void setHistorySize(int historySize) { this.historySize = historySize; } // ################################################################################ // END OF ADJUSTABLES // ################################################################################ private Map<Integer, List<DataPosition2D>> lastValues; /* (non-Javadoc) * @see org.squidy.manager.model.AbstractNode#onStart() */ @Override public void onStart() { super.onStart(); lastValues = new HashMap<Integer, List<DataPosition2D>>(); } /* (non-Javadoc) * @see org.squidy.manager.model.AbstractNode#onStop() */ @Override public void onStop() { super.onStop(); lastValues.clear(); lastValues = null; } /** * @param dataPosition2D * @return */ public IData process(DataPosition2D dataPosition2D) { if (!dataPosition2D.hasAttribute(TUIO.ANGLE_A)) { return dataPosition2D; } if (dataPosition2D.hasAttribute(TUIO.FIDUCIAL_ID)) { int fiducialId = (Integer) dataPosition2D.getAttribute(TUIO.FIDUCIAL_ID); List<DataPosition2D> lastPositions = lastValues.get(fiducialId); if (lastPositions == null) { lastPositions = new ArrayList<DataPosition2D>(); lastValues.put(fiducialId, lastPositions); } if (lastPositions.size() >= historySize) { lastPositions.remove(0); } lastPositions.add(dataPosition2D); List<DataPosition2D> medianCollection = new ArrayList<DataPosition2D>(); medianCollection.addAll(lastPositions); // Sorts last rotations collection Collections.sort(medianCollection, new Comparator<DataPosition2D>() { public int compare(DataPosition2D o1, DataPosition2D o2) { Float v1 = (Float) o1.getAttribute(TUIO.ANGLE_A); Float v2 = (Float) o2.getAttribute(TUIO.ANGLE_A); return v1.compareTo(v2); } }); return medianCollection.get(medianCollection.size() / 2); } return dataPosition2D; } }