package jasext.hist.function;
import jas2.hist.*;
import java.awt.*;
import java.awt.event.*;
import jas2.util.*;
import javax.swing.*;
public class PolynomialFunction extends AbstractPolynomialFunction implements FunctionAdvancedOptions
{
/**
*
*/
private static final long serialVersionUID = 1L;
PolynomialFunction(double[] coefficients)
{
order = coefficients.length - 1;
/*
* for example, a 2nd order equation
* would have three coeffieicients
*/
p = coefficients;
/*
* the parameters will be the coeffieients
*/
}
public PolynomialFunction(double xmin, double xmax, double ymin, double ymax)
{
order = 2;
p = new double[3];
final double xVertex = (xmax - xmin) / 2.0;
p[0] = (ymax - ymin) / Math.pow(xmax - xVertex, 2);
p[1] = -p[0] * (xmax - xmin);
p[2] = ymin - p[0] * xVertex * xVertex - p[1] * xVertex;
}
public void openAdvancedDialog(Frame f, JASHist hist)
{
new PolynomialFunctionAdvancedDialog(f);
}
private class PolynomialFunctionAdvancedDialog extends JASDialog
{
/**
*
*/
private static final long serialVersionUID = 1L;
private JASTextField tf;
private Frame f;
private JASHistPropertyDialog pd;
PolynomialFunctionAdvancedDialog(Frame f)
{
super(f, "Advanced...", true, JASDialog.OK_BUTTON);
this.f = f;
Container c = getContentPane();
JPanel p = new JPanel(new GridLayout(4,1));
p.add(new JLabel("Set the order of the polynomial. "));
p.add(new JLabel("Note that changing the order will "));
p.add(new JLabel("erase all existing polynomial "));
p.add(new JLabel("coefficients."));
tf = new JASTextField(String.valueOf(order));
c.add(BorderLayout.NORTH, p);
c.add(BorderLayout.SOUTH, tf);
pack();
doModal();
}
public void onOK()
{
try
{
int temp = Integer.parseInt(tf.getText());
if (temp < 2)
{
JOptionPane.showMessageDialog(f, "Order must be at least 2", "Error",
JOptionPane.ERROR_MESSAGE);
return;
}
if (temp != order)
{
order = temp;
clearFitParams();
clearFit();
p = new double[order + 1];
for (int i = 0; i < p.length; i++)
p[i] = Math.random() * (Math.random() > 0.5 ? 5.0 : -2.0);
setChanged();
dispose();
}
else
dispose();
}
catch (NumberFormatException e)
{
JOptionPane.showMessageDialog(f, "Incorrect number format", "Error...",
JOptionPane.ERROR_MESSAGE);
}
}
}
}
abstract class AbstractPolynomialFunction extends Fittable1DFunction implements HasHandles
{
public final double valueAt(double x)
{
double answer = p[order];
for (int i = 0; i < order; i++)
answer += (Math.pow(x, order - i) * p[i]);
return answer;
}
public final double valueAt(double x, double[] a)
{
double answer = a[order];
for (int i = 0; i < order; i++)
answer += (Math.pow(x, order - i) * a[i]);
return answer;
}
public final String[] getParameterNames()
/*
* Parameter names are simply
* letters beginning at "A" and
* proceeding through "Z", theb "AA"
* throught to "ZZ", then "AAA" through
* to "ZZZ", then "AAAA", etc.
*/
{
String[] s = new String[order + 1];
new jas2.util.ArbitraryNameGenerator().fillArray(s);
return s;
}
public final double[] getParameterValues()
{
return p;
}
public final void setParameter(int index, double value) throws InvalidFunctionParameter
{
try
{
p[index] = value;
}
catch (ArrayIndexOutOfBoundsException e)
{
throw new IllegalArgumentException("Invalid index to setParameter");
}
clearFit();
setChanged();
}
public final void setFit(Fitter fit, double[] value) throws InvalidFunctionParameter
{
if (value.length != p.length)
throw new IllegalArgumentException("Argument to setParameters is of wrong length");
p = value;
setFit(fit);
setChanged();
}
public String getTitle()
{
return "Polynomial (order " + order + ")";
}
public final Handle[] getHandles(double xLow, double xHigh, double yLow, double yHigh)
// using notation f(x) = ax^2 + bx + c
{
xmin = xLow; xmax = xHigh; ymin = yLow; ymax = yHigh;
/*
* copying these parameters over to instance
* variables makes them accessible to the
* anonymous class definitions below
*/
Handle[] result;
if (order == 2)
{
result = new Handle[2];
result[0] = new Handle()
{
// this handle is the vertex of the parabola
/*
* many formulas here use the formula
* that x at the vertex is -b/2a
*/
public void moveTo(double x, double y)
{
p[1]/*b*/ = -2.0 * p[0]/*a*/ * x;
p[2]/*c*/ = y - p[0]/*a*/ * x * x - p[1]/*b*/ * x;
/* c = y - ax^2 - bx */
/*
* a is left unchanged, so moving the
* vertex handle does not affect parabola
* shape
*/
clearFit();
setChanged();
}
public double getX()
{
return -p[1]/*b*/ / (2 * p[0]/*a*/); /* = -b / 2a */
}
public double getY()
{
return valueAt(getX());
}
};
result[1] = new Handle()
{
public void moveTo(double x, double y)
{
final double xVertex = -p[1]/*b*/ / (2.0 * p[0]/*a*/);
final double yVertex = valueAt(xVertex);
/*
* The vertex will not move, although a, b, and c change.
* These vales for the vertex are true no matter where
* the handle is moved to.
*/
p[0]/*a*/ = (y - yVertex) / Math.pow(x - xVertex, 2);
p[1]/*b*/ = -2.0 * p[0]/*a*/ * xVertex;
p[2]/*c*/ = y - (p[0]/*a*/ * x * x) - (p[1]/*b*/ * x);
clearFit();
setChanged();
}
public double getY()
{
return valueAt(getX());
}
public double getX()
{
final double xVertex = -p[1]/*b*/ / (2 * p[0]/*a*/);
final double xMiddle = (xmax - xmin) / 2.0;
if (xVertex > xMiddle && xVertex < xmax)
return ( (xVertex - xmin) / 2.0 ) + xmin;
else if (xVertex <= xMiddle && xVertex > xmin)
return xmax - ( (xmax - xVertex) / 2.0 );
else
return xMiddle;
}
};
}
else // order != 2
{
result = new Handle[1];
/* there will be one handle that can move the function up and down only */
result[0] = new Handle()
{
public void moveTo(double x, double y)
{
p[order] = 0.0;
p[order] = y - valueAt(x);
clearFit();
setChanged();
}
public double getY()
{
return valueAt(getX());
}
public double getX()
{
return (xmax - xmin) / 2.0;
}
};
}
return result;
}
protected double[] p; // coefficients
protected int order;
private double xmin, xmax, ymin, ymax;
}
Ads help maintain this website.