///////////////////////////////////////////////////////////////////////
//
// GraphIT: Plot curves in a framed graph area. 
// Version of 8/25/00, 3:40PM
//
///////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2004 Integre Technical Publishing.  All Rights Reserved.
//
// Revised by:      B. F. Caviness, Aug 2000
//
///////////////////////////////////////////////////////////////////////

import java.awt.*;
import java.applet.Applet;

public class GraphIT extends Applet {

  private TrigCurve trigCurve    = null;

  public void init() {
    trigCurve = new TrigCurve( TrigCurve.SINCURVE );
  } 
    
  public String getAppletInfo() {
    return "GraphIT (named " + getParameter("name") + ") by A. Diaz, B. Trager, R. Sutor";
  }

  public void setParam( int p ) {
    trigCurve.setParam( p );
  }

  public void setCurve( int curveID ) {
    trigCurve.setCurve( curveID );
  } 

  public void update(Graphics g) {	// Override update() to do away with redrawing background
    paint(g);						// to help control flashing
  }

  public void paint(Graphics g) {
    Dimension d = size();
    Dimension offDimension = new Dimension(d);
    Image     offImage     = null;         
    Graphics  offGraphics  = null;

    offDimension.width -= 8; offDimension.height -= 8;
    offImage = createImage(offDimension.width, offDimension.height);
    offGraphics = offImage.getGraphics(); // Paint image off screen to help control flashing
	setBackground(Color.white);           // set background color for this component

    // draw axes and curve
    offGraphics.setColor(Color.black);
	trigCurve.drawAxes( offGraphics, offDimension );	 
	trigCurve.draw( offGraphics, offDimension );

    //Paint the image onto the screen.
    g.drawImage(offImage, 4, 4, this);
    offGraphics.dispose();          // dispose of this graphics obj for efficency
    offImage.flush();

    // Draw frame around graph area
    g.setColor(Color.black);							
    g.draw3DRect(0, 0, d.width - 1, d.height - 1, true);
    g.draw3DRect(3, 3, d.width - 7, d.height - 7, false);
  }
}		  								// end of class GraphIT

class TrigCurve{

  // Public named constants
  public static final int SINCURVE = 1;
  public static final int COSCURVE = 2;
  public static final int CURVE_INIT_PARAM = 10;

  private int curveID = SINCURVE;
  private int param   = CURVE_INIT_PARAM;

  public TrigCurve( int curveID ) {
    this.curveID = curveID;
  }

  public void setParam( int p ) {
    param = p;
  }

  public void setCurve( int curveID ) {
    this.curveID = curveID;
  }

  public void drawAxes(Graphics g, Dimension d) {	
    int xone  = d.width;
    int xhalf = xone / 2;
    int yone  = d.height;
	int yhalf = yone / 2;

	g.setColor(Color.black);
	g.drawLine(0, yhalf, xone, yhalf);
	g.drawLine(xhalf, 0, xhalf, yone);
  }

  // Method for drawing the curve
  public void draw(Graphics g, Dimension d) {
	int xone   = d.width;
	int yone   = d.height;
	int ypos   = param*yone/100;
	int yscale = yone/2;

	g.setColor(Color.red);
	double xmin = -10.0;
	double xmax = 10.0;
	double xrange = xmax - xmin;

	double xval = xmin;
	double yval = evaluateCurve(param/20.0*xval);
	int x1 = (int)((xval-xmin)/xrange * xone);
	int y1 = (int)((-yval+1)*yscale);

	int nsteps = 500;
	double xstep = xrange / nsteps ;
			
	int x2 = 0, y2 = 0;
	for (int i=0; i<nsteps; i++) {	
      xval = xval + xstep;
	  yval = evaluateCurve(param/20.0*xval);
	  x2 = (int)((xval-xmin)/xrange * xone);
	  y2 = (int)((-yval+1)*yscale);
	  g.drawLine(x1, y1, x2, y2);
	  x1 = x2;
	  y1 = y2;
	}
  }

    double evaluateCurve( double p ) {
    double value = 0;
    switch( curveID ) {
	  case SINCURVE: value = Math.sin( p ); 
		             break;
	  case COSCURVE: value = Math.cos( p );
		             break;
	  default:       value = Math.sin( p );
		             break;
    }
    return value;
  }
}
