import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;

/** Supplies a static method to plot an array of x values against
    an array of y values in a separate frame.*/
public class Plotter
{
    public static void plot(double[] xVals,double[] yVals,String title)
    {  //Note: Do NOT exit application on closing the plot.
	DrawFrame f = new DrawFrame();
        f.initialise(xVals,yVals,title);
	f.setVisible(true);
    }
}

/** A frame that contains a panel with drawings */
class DrawFrame extends JFrame
{
    public static final int WIDTH = 700;
    public static final int HEIGHT = 500;

    public DrawFrame(){}

    public void initialise(double[] xVals,double[] yVals,String title)
    {
        setTitle(title);
        setSize(WIDTH,HEIGHT);
	DrawPanel panel = new DrawPanel();
	panel.setGraphData(xVals,yVals);
	getContentPane().add(panel);
    }
}

/** A panel that displays a line joining data points*/
class DrawPanel extends JPanel
{
    private double[] xVals,yVals;

    public DrawPanel(){}

    public void setGraphData(double[] x,double[] y)
    {
	this.xVals = x;
	this.yVals = y;
    }

    public void paintComponent(Graphics g)
    {
      BasicStroke bs;                  // Ref to BasicStroke
      int i;                           // Loop index
      Line2D line;                     // Ref to line
      float[] solid = {12.0f,0.0f};    // Solid line style

      // Cast the graphics object to Graph2D
      Graphics2D g2 = (Graphics2D) g;

      // Get plot size
      Dimension size = getSize();

      // Set background color
      g2.setColor( Color.white );
      g2.fill(new Rectangle2D.Double(0,0,size.width,size.height));

      // Set the Color and BasicStroke
      g2.setColor(Color.black);
      float strokeWidth = 1.0f;
      bs = new BasicStroke( strokeWidth, BasicStroke.CAP_SQUARE,
                            BasicStroke.JOIN_MITER, 1.0f,
                            solid, 0.0f );
      g2.setStroke(bs);

      double xMax,yMax,xMin,yMin,deltaX,deltaY;
      xMax=xVals[0];
      xMin=xMax;
      yMax=yVals[0];
      yMin=yMax;
      for (i=1;i<xVals.length; i++)
      {
	  if (xVals[i] > xMax) xMax = xVals[i];
	  if (yVals[i] > yMax) yMax = yVals[i];
	  if (xVals[i] < xMin) xMin = xVals[i];
	  if (yVals[i] < yMin) yMin = yVals[i];
      }
      deltaX = xMax - xMin;
      deltaY = yMax - yMin;

      double xScale,yScale;
      xScale = (size.width)/(deltaX);
      yScale = (size.height)/(deltaY);

      double[] xScaled = new double[xVals.length];
      double[] yScaled = new double[yVals.length];

      for (i=0; i<xVals.length; i++)
      {
          xScaled[i] = (xVals[i]-xMin)*xScale;
          yScaled[i] = size.height - (yVals[i]-yMin)*yScale;
      }

      // Plot curve
      for ( i = 0; i < xVals.length-1; i++ ) {
         line = new Line2D.Double(xScaled[i], yScaled[i],
                                  xScaled[i+1],yScaled[i+1]);
         g2.draw(line);
      }
   }
}
