
org.monte.media.AbstractSplineInterpolator Maven / Gradle / Ivy
/*
* @(#)AbstractSplineInterpolator.java 1.0 2012-01-25
*
* Copyright (c) 2012 Werner Randelshofer, Goldau, Switzerland.
* All rights reserved.
*
* You may not use, copy or modify this file, except in compliance with the
* license agreement you entered into with Werner Randelshofer.
* For details see accompanying license terms.
*/
package org.monte.media;
import java.awt.geom.Point2D.Float;
import java.util.Comparator;
import java.util.ArrayList;
import java.awt.geom.Point2D;
import java.util.Arrays;
import static java.lang.Math.*;
/**
* {@code AbstractSplineInterpolator}.
*
* @author Werner Randelshofer
* @version 1.0 2012-01-25 Created.
*/
public abstract class AbstractSplineInterpolator extends Interpolator {
/** Note: (x0,y0) and (x1,y1) are implicitly (0, 0) and (1,1) respectively. */
private LengthItem[] fractions;
private static class LengthItem {
public float x, y, t;
public LengthItem(float x, float y, float t) {
this.x = x;
this.y = y;
this.t = t;
}
public LengthItem(Float p, float t) {
this.x = p.x;
this.y = p.y;
this.t = t;
}
@Override
public String toString() {
return "LengthItem{" + "x=" + x + ", y=" + y + ", t=" + t + '}';
}
}
private static class FractionComparator implements Comparator {
@Override
public int compare(LengthItem o1, LengthItem o2) {
if (o1.x > o2.x) {
return 1;
} else if (o1.x < o2.x) {
return -1;
}
return 0;
}
}
private static FractionComparator fractionComparator = new FractionComparator();
public AbstractSplineInterpolator() {
this(0f, 1f);
}
/**
* Creates a new interpolator which interpolates from 0 to 1 within the
* specified timespan.
*/
public AbstractSplineInterpolator(long timespan) {
this(0f, 1f, timespan);
}
/**
* Creates a new interpolator which interpolates into the specified
* direction within one second.
*
* @param reverse Set this to true, if you want to interpolate from 1 to 0
* instead of from 0 to 1.
*/
public AbstractSplineInterpolator(boolean reverse) {
this((reverse) ? 1f : 0f, (reverse) ? 0f : 1f);
}
/**
* Creates a new interpolator which interpolates from the specified
* start value to the specified end value within one second.
*
* @param startValue A value between 0 and 1.
* @param endValue A value between 0 and 1.
*/
public AbstractSplineInterpolator(float startValue, float endValue) {
this(startValue, endValue, 1000);
}
/**
* Creates a new interpolator which interpolates from the specified
* start value to the specified end value within the specified timespan.
*
* @param startValue A value between 0 and 1.
* @param endValue A value between 0 and 1.
* @param timespan A timespan in milliseconds.
*/
public AbstractSplineInterpolator(float startValue, float endValue, long timespan) {
super(startValue,endValue,timespan);
}
/** This method must be called by the subclass in the constructor.
*
* @param N
*/
protected void updateFractions(int N) {
fractions = new LengthItem[N];
Float p = new Float();
for (int i = 0; i < N; i++) {
float t = (float) i / (N - 1);
fractions[i] = new LengthItem(getXY(t, p), t);
}
}
/**
* Evaluates the spline function at time t, and clamps the result value between 0
* and 1.
*/
@Override
public final float getFraction(float t) {
LengthItem p1 = new LengthItem(t, 0f, t);
LengthItem p2 = new LengthItem(t, 0f, t);
int index = Arrays.binarySearch(fractions, p1, fractionComparator);
if (index >= 0) {// we have found the exact value
return fractions[index].y;
}
// we found the next bigger value
index = -1 - index;
if (index == fractions.length) {
return fractions[fractions.length - 1].y;
}
if (index == 0) {
return fractions[0].y;
}
p1 = fractions[max(0, index - 1)];
p2 = fractions[min(fractions.length - 1, index)];
float weight = (p2.x - t) / (p2.x - p1.x);
float s = p1.t * weight + p2.t * (1 - weight);
return getY(s);
}
/**
* Evaluates the spline function at curve parameter time t.
*/
protected abstract Float getXY(float t, Float p);
/**
* Evaluates the spline function at curve parameter time t.
*/
protected abstract float getY(float t);
/** This method is empty.
* Subclasses don't have to call super.update(fraction). */
@Override
protected void update(float fraction) {
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy