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.