/** * Copyright (C) 2009-2014 Cars and Tracks Development Project (CTDP). * * This program 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 2 * of the License, or (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ package net.ctdp.rfdynhud.valuemanagers; /** * Interpolates a float value along time. * * @author Marvin Froehlich (CTDP) */ public class ValueInterpolater implements ManagedValue { public static enum BoundaryType { CIRCULAR, BIDIRECTIONAL, ; } private final BoundaryType boundaryType; private final float minValue; private final float maxValue; private final float startValue; private final float speed; private final long speedNanos; private float value; private long startTime = 0L; /** * Gets the used {@link BoundaryType}. * * @return the used {@link BoundaryType}. */ public final BoundaryType getBoundaryType() { return ( boundaryType ); } /** * Gets the minimum value. * * @return the minimum value. */ public final float getMinValue() { return ( minValue ); } /** * Gets the maxmum value. * * @return the maxmum value. */ public final float getMaxValue() { return ( maxValue ); } /** * Gets the start value (set by the {@link #init(long)} method). * * @return the start value. */ public final float getStartValue() { return ( startValue ); } /** * Gets the speed. * This is the time in seconds for moving from minValue to maxValue. * * @return the speed in seconds. */ public final float getSpeed() { return ( speed ); } /** * Sets the current value. * * @param value */ private void setValue( float value ) { this.value = value; } /** * Gets the current value. * * @return the interpolated value */ public final float getValue() { return ( value ); } /** * {@inheritDoc} */ @Override public void init( long nanoTime ) { setValue( getStartValue() ); this.startTime = nanoTime; } /** * {@inheritDoc} */ @Override public void update( long nanoTime, long frameCounter, boolean force ) { if ( boundaryType == BoundaryType.CIRCULAR ) { long t = ( nanoTime - startTime ) % speedNanos; float tf = (float)( t / 1000000000.0 ); float nt = tf / speed; this.value = minValue + ( maxValue - minValue ) * nt; } else if ( boundaryType == BoundaryType.BIDIRECTIONAL ) { long t = ( nanoTime - startTime ); float n = (float)( t / (double)speedNanos ); int m = (int)( n % 2.0f ); if ( m == 0 ) t = t % speedNanos; else t = speedNanos - ( t % speedNanos ); float tf = (float)( t / 1000000000.0 ); float nt = tf / speed; this.value = minValue + ( maxValue - minValue ) * nt; } } public final void update( long nanoTime ) { update( nanoTime, -1, false ); } public ValueInterpolater( BoundaryType boundaryType, float minValue, float maxValue, float startValue, float speed ) { if ( boundaryType == null ) throw new IllegalArgumentException( "boundaryType must not be null." ); this.boundaryType = boundaryType; this.minValue = minValue; this.maxValue = maxValue; this.startValue = startValue; this.speed = speed; this.speedNanos = (long)( 1000000000.0 * speed ); } }