content: package tim.prune.correlate;
  
  import tim.prune.data.DataPoint;
  import tim.prune.data.MediaObject;
  
  /**
   * Class to hold a pair of points used to hold the result of correlation
   */
  public class PointMediaPair
  {
  	private final MediaObject _media;
  	private DataPoint _pointBefore = null;
  	private DataPoint _pointAfter = null;
  	private long _secondsBefore = 1L;
  	private long _secondsAfter = -1L;
  
  
  	/**
  	 * Constructor
  	 * @param inMedia media object
  	 */
  	public PointMediaPair(MediaObject inMedia) {
  		_media = inMedia;
  	}
  
  	/**
  	 * Add a point to the pair
  	 * @param inPoint data point
  	 * @param inSeconds number of seconds time difference, positive means point later
  	 */
  	public void addPoint(DataPoint inPoint, long inSeconds)
  	{
  		// Check if point is closest point before
  		if (inSeconds <= 0)
  		{
  			// point stamp is before media stamp
  			if (inSeconds > _secondsBefore || _secondsBefore > 0L)
  			{
  				// point stamp is nearer to media
  				_pointBefore = inPoint;
  				_secondsBefore = inSeconds;
  			}
  		}
  		// Check if point is closest point after
  		if (inSeconds >= 0)
  		{
  			// point stamp is after media stamp
  			if (inSeconds < _secondsAfter || _secondsAfter < 0L)
  			{
  				// point stamp is nearer to media
  				_pointAfter = inPoint;
  				_secondsAfter = inSeconds;
  			}
  		}
  	}
  
  
  	/**
  	 * @return Media object
  	 */
  	public MediaObject getMedia() {
  		return _media;
  	}
  
  	/**
  	 * @return the closest point before the media
  	 */
  	public DataPoint getPointBefore() {
  		return _pointBefore;
  	}
  
  	/**
  	 * @return number of seconds between media and subsequent point
  	 */
  	public long getSecondsBefore() {
  		return _secondsBefore;
  	}
  
  	/**
  	 * @return the closest point after the media
  	 */
  	public DataPoint getPointAfter() {
  		return _pointAfter;
  	}
  
  	/**
  	 * @return number of seconds between previous point and media
  	 */
  	public long getSecondsAfter() {
  		return _secondsAfter;
  	}
  
  	/**
  	 * @return true if both points found
  	 */
  	public boolean isValid() {
  		return getPointBefore() != null && getPointAfter() != null;
  	}
  
  	/**
  	 * @return the fraction of the distance along the interpolated line
  	 */
  	public double getFraction()
  	{
  		if (_secondsAfter == 0L) return 0.0;
  		return (-_secondsBefore * 1.0 / (-_secondsBefore + _secondsAfter));
  	}
  
  	/**
  	 * @return the number of seconds to the nearest point
  	 */
  	public long getMinSeconds() {
  		return Math.min(_secondsAfter, -_secondsBefore);
  	}
  
  	/**
  	 * @return angle from media to nearest point in radians
  	 */
  	public double getMinRadians()
  	{
  		double totalRadians = DataPoint.calculateRadiansBetween(_pointBefore, _pointAfter);
  		double frac = getFraction();
  		return totalRadians * Math.min(frac, 1-frac);
  	}
  }
  