This class implements the representation of an interpolated Spline curve.
The curve described by such an object interpolates an arbitrary number of
fixed points called
nodes. The distance between two nodes should
currently be constant. This is about to change in a later version but it can
last a while as it's not really needed. Nevertheless, if you need the
feature, just
write me
a note and I'll write it asap.
The interpolated Spline curve can't be described by an polynomial analytic
equation, the degree of which would be as high as the number of nodes, which
would cause extreme oscillations of the curve on the edges.
The solution is to split the curve accross a lot of little
intervals :
an interval starts at one node and ends at the next one. Then, the
interpolation is done on each interval, according to the following conditions :
- the interpolated curve is degree 3 : it's a cubic curve ;
- the interpolated curve contains the two points delimiting the interval.
This condition obviously implies the curve is continuous ;
- the interpolated curve has a smooth slope : the curvature has to be the
same on the left and the right sides of each node ;
- the curvature of the global curve is 0 at both edges.
Every part of the global curve is represented by a cubic (degree-3)
polynomial, the coefficients of which have to be computed in order to meet
the above conditions.
This leads to a n-unknow n-equation system to resolve. One can resolve an
equation system by several manners ; this class uses the Jacobi iterative
method, particularly well adapted to this situation, as the diagonal of the
system matrix is strong compared to the other elements. This implies the
algorithm always converges ! This is not the case of the Gauss-Seidel
algorithm, which is quite faster (it uses intermediate results of each
iteration to speed up the convergence) but it doesn't converge in all the
cases or it converges to a wrong value. This is not acceptable and that's why
the Jacobi method is safer. Anyway, the gain of speed is about a factor of 3
but, for a 100x100 system, it means 10 ms instead of 30 ms, which is a pretty
good reason not to explore the question any further :)
Here is a little piece of code showing how to use this class :
// ... float[] nodes = {3F, 2F, 4F, 1F, 2.5F, 5F, 3F}; Spline3 curve =
new Spline3(nodes); // ... public void paint(Graphics g) { int[] plot =
curve.getPlots(); for (int i = 1; i <32n; i++) { g.drawLine(i - 1, plot[i -
1], i, plot[i]); } } // ...
converge
protected boolean converge()
Test if the Jacobi resolution of the equation system converges. It's OK
if A has a strong diagonal.
debugCheck
public void debugCheck()
Manual check of the curve at the interpolated points.
getDefaultMaxIterations
public int getDefaultMaxIterations()
getDefaultPrecision
public float getDefaultPrecision()
getMaxIterations
public int getMaxIterations()
getPlots
public int[] getPlots(int width,
int height)
Computes drawable plots from the curve for a given draw space. The values
returned are drawable vertically and from the bottom of a Panel.
width
- width within the plots have to be computedheight
- height within the plots are expected to be drawed
- drawable plots within the limits defined, in an array of int (as
many int as the value of the
width
parameter)
getPrecision
public float getPrecision()
interpolation
protected void interpolation()
Computes the coefficients of the Spline interpolated curve, on each
interval. The matrix system to resolve is AX=B
jacobi
protected void jacobi()
Resolves the equation system by a Jacobi algorithm. The use of the slower
Jacobi algorithm instead of Gauss-Seidel is choosen here because Jacobi
is assured of to be convergent for this particular equation system, as
the system matrix has a strong diagonal.
precision
protected float precision(float[] oldX,
float[] newX)
Computes the current precision reached.
setMaxIterations
public void setMaxIterations(int iterations)
setPrecision
public void setPrecision(float precision)
setToDefaultMaxIterations
public void setToDefaultMaxIterations()
setToDefaultPrecision
public void setToDefaultPrecision()
value
public float value(float t)
Computes a (vertical) Y-axis value of the global curve.