Java/Advanced Graphics/Math Functions

Материал из Java эксперт
Перейти к: навигация, поиск

Calculate the arithmetic function

/*************************************************************************
*                                                                        *
*  This source code file, and compiled classes derived from it, can      *
*  be used and distributed without restriction, including for commercial *
*  use.  (Attribution is not required but is appreciated.)               * 
*                                                                        *
*   David J. Eck                                                         *
*   Department of Mathematics and Computer Science                       *
*   Hobart and William Smith Colleges                                    *
*   Geneva, New York 14456,   USA                                        *
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
*                                                                        *
*************************************************************************/

import java.awt.*;
import java.applet.Applet;
import edu.hws.jcm.data.*;  // Packages that define some JCM classes.
import edu.hws.jcm.awt.*;

public class ArithmeticApplet extends Applet {
   /* The makeLabel() routine is just a small utility routine
      that makes a label containing a given string.  Labels made with
      this routine are used in the little boxes on the left side
      of the above applet. */
   Label makeLabel(String str) {
      Label lab = new Label(str, Label.RIGHT);
      lab.setBackground(new Color(255,255,220));
      lab.setForeground(Color.blue);
      return lab;
   }
   

   /* The makeDisplayLable() routine is a small utility routine
      that makes a "DisplayLabel".  A DisplayLabel is one of the
      JCM components whose purpose is to display one or more
      Values.  A "Value" is just an object that implements the
      interface edu.hws.jcm.data.Value.  It has an assoicated numeric
      value that can be retrieved with getVal().  This is a fundamental
      interface in the JCM system which can represent constant
      values, variables, and results of computations. 
      DisplayLabels are used for the lower four boxes on the
      right of the above applet. */
   Label makeDisplayLabel(Value val) {
      Label lab = new DisplayLabel("#",val);
         // In the string displayed by this label, the # is
         //    replaced by the value of val.
      lab.setBackground(new Color(255,255,220));
      lab.setForeground(Color.red);
      lab.setAlignment(Label.CENTER);
      return lab;
   }
   

   /* The standard Applet routine, init(), sets up and lays out
      the applet.  For a JCM Applet, there is usually not much to
      do besides setting it up.  The JCM components are "active",
      and they pretty much take care of themselves if they are
      set up properly. */
   public void init() {
   
      setBackground(Color.blue);       // Set the background color and
      setLayout(new BorderLayout());   //   layout of the applet as a whole.
                                       //   The whole applet will be filled with
                                       //   a single JCMPanel.
      
      JCMPanel main = new JCMPanel(6,2,2);  // The applet will be built with
                                            //   JCMPanels, a subclass of Panel,
                                            //   defined in edu.hws.jcm.awt.
                                            //   If an applet is constructed using
                                            //   JCMPanels, a lot of the JCM setup
                                            //   is taken care of automatically
                                            //   (at some possible loss of efficiency).
                                            // This JCMPanel constructor creates
                                            //   a panel with a GridLayout with
                                            //   6 rows and two columns, and with
                                            //   2-pixel gaps between the rows 
                                            //   and columns.
                                            
      add(main, BorderLayout.CENTER);  // The JCMPanel will fill the whole applet.
      
      main.setInsetGap(2);  // This sets the "Insets" around the edges of the panel.
                            //   It allows a two-pixel-wide blue border to show
                            //   around the edges.
      
      Parser parser = new Parser();  // A Parser can be used to turn strings
                                     //   into Expressions.  An Expression is a
                                     //   Value that is computed from some mathematical
                                     //   formula such as x+y or 3*sin(x^2-2).
      VariableInput xInput = new VariableInput("x","0",parser);
      VariableInput yInput = new VariableInput("y","0",parser);
             // A VariableInput is a text input box where the user can
             //    input the value of a variable.  The variable can be used
             //    in Expressions, provided that the variable is registered 
             //    with the Parser that makes the Expressions.  The two lines
             //    above make two VariableInputs for inputting the values of
             //    two variables.  The names of the variables are "x" and
             //    "y", and they are registered with the Parser named parser
             //    which was created above.
      
      
      main.add(makeLabel("Input x = "));  // Add components for the top row of the applet.
      main.add(xInput);
      
      main.add(makeLabel("Input y = "));  // Components for the second row.
      main.add(yInput);
      main.add(makeLabel("x + y = "));    // Components for the third row.
      main.add(makeDisplayLabel( parser.parse("x+y") ));
           // Here, parser.parse("x+y") creates an Expression that represents
           //    the value of the formula x+y.  x and y are the names for the
           //    values in the input boxes xInput and yInput, so this formula
           //    represents the sum of the numbers input by the user. Note that
           //    and Expression is a type of Value object, and so can be passed
           //    to the makeDisplayLabel() routine, which is defined above.
           //    This routine creates a label that shows the value of the
           //    Expression.
           // Note:  For the simple expression x+y, I could have used the
           //    ValueMath class to create the value object, instead of a parser.
           //    Just replace parser.parse("x+y") with:  new ValueMath(xInput,yInput,"+").
           //    ValueMath objects would let me do without the parser entirely in
           //    this applet, but parsers are necessary for more complicated expressions,
           //    and they are used for expressions entered by the user.
      main.add(makeLabel("x - y = "));    // Components for the fourth row.
      main.add(makeDisplayLabel( parser.parse("x-y") ));
      main.add(makeLabel("x * y = "));    // Components for the fifth row.
      main.add(makeDisplayLabel( parser.parse("x*y") ));
      main.add(makeLabel("x / y = "));    // Components for the sixth row.
      main.add(makeDisplayLabel( parser.parse("x/y") ));

      Controller c = main.getController();  // A Controller is another of the
                                            //   fundamental JCM classes.  A controller
                                            //   makes things happen.  It "listens" for
                                            //   user actions and does the computations
                                            //   necessary to update any JCM components
                                            //   that it controls.  A JCMPanel has a 
                                            //   controller for recomputing the JCM
                                            //   components in the panel.  Calling
                                            //   main.getController() retrieves the
                                            //   Controller for the JCMPanel, main.
      xInput.setOnTextChange(c);    // A Controller must still be told what user
      yInput.setOnTextChange(c);    //    actions to listen for.  These two lines set
                                    //    up the Controller, c, to listen for any
                                    //    changes in the text in the input boxes
                                    //    xInput and yInput.  Thus, every time the
                                    //    user types a character in one of these
                                    //    boxes, all the DisplayLabels are recomputed.
   } // end init()
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         java.applet.Applet app = new ArithmeticApplet();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }  
   
} // end class ArithmeticApplet





Contouring

import java.awt.*;
import java.applet.*;
import java.net.URL;
import java.util.*;
import graph.*;
/*************************************************************************
**
**    Applet example6
**                                              Version 1.0   February 1996
**
**************************************************************************
**    Copyright (C) 1996 Leigh Brookshaw
**
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation; either version 2 of the License, or
**    (at your option) any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************
**
**    This applet demonstrates the the contouring cababilities
**    of the Contour class
**
*************************************************************************/
public class example6 extends Applet {
      LoadData dynamic;
      Contour graph;
      Label title;
      Axis    xaxis;
      Axis    yaxis;

      public void init() {
        int i;
        int j;
/*
**      Instantiate the Contour class and calculate the data
*/
        graph = new Contour();
        graph.setDataBackground(new Color(0.933f,0.914f,0.749f));
        graph.setContourColor(new Color(0.180f,0.545f,0.341f));
        graph.setLabelledContourColor(new Color(0.5f,.0f,0.0f));
        graph.setLabelPrecision(2);
        graph.setLabelSignificance(2);

//        this.showStatus("Creating Data to Contour!");
        createGrid(graph);
        graph.square       = true;
/*
**      Build the title and place it at the top of the graph
*/
        graph.setFont(new Font("TimesRoman",Font.PLAIN,25));
        title = new Label("Contouring Example", Label.CENTER);
        title.setFont(new Font("TimesRoman",Font.PLAIN,25));
        setLayout( new BorderLayout() );
        add("North",  title);
        add("Center", graph);
/*
**      Instantiate the xaxis and attach the dataset.
*/
        xaxis = graph.createXAxis();
        xaxis.setTitleText("X_axis");
        xaxis.setTitleColor(Color.magenta);
        xaxis.setTitleFont(new Font("TimesRoman",Font.ITALIC,25));
        xaxis.setLabelFont(new Font("Helvetica",Font.PLAIN,20));

/*
**      Instantiate the yaxis and attach the dataset.
*/
        yaxis = graph.createYAxis();
        yaxis.setTitleText("Y_axis");
        yaxis.setTitleColor(Color.magenta); 
        yaxis.setTitleFont(new Font("TimesRoman",Font.ITALIC,25));
        yaxis.setLabelFont(new Font("Helvetica",Font.PLAIN,20));

      }

      public void createGrid(Contour graph) {
         int i,j;
         int count;
         
         int nx = 50;
         int ny = 50;
         double xmin = -1.0;
         double xmax =  1.0;
         double ymax =  1.0;
         double ymin = -1.0;

         double array[] = new double[nx*ny];
         double x, y, rad;
         double h1, h2, h3;
         h1 = 0.5*0.5;
         h2 = 0.75*0.75;
         h3 = 0.25*0.25;
         count = 0;
         for(j=0; j<ny; j++) {
             y = 2.0*(double)j/(double)(ny-1) - 1.0;
             for(i=0; i<nx; i++) {
                x = 2.0*(double)i/(double)(nx-1) - 1.0;
                rad = (x-0.5)*(x-0.5) + (y+0.5)*(y+0.5);
                array[count] = Math.exp( -rad/h1 );
                rad = (x+0.3)*(x+0.3) + (y-0.75)*(y-0.75);
                array[count] += Math.exp( -rad/h2 );
                rad = (x+0.7)*(x+0.7) + (y+0.6)*(y+0.6);
                array[count] += Math.exp( -rad/h3 );

                count++;  
        }
     }
           graph.setGrid(array,nx,ny);
           graph.setRange(xmin,xmax,ymin,ymax);
           graph.setLimitsToGrid(true);
           graph.setLabelLevels(3);
           graph.setNLevels(20);
      }
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new example6();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }      
}





Derivatives

/*************************************************************************
*                                                                        *
*  This source code file, and compiled classes derived from it, can      *
*  be used and distributed without restriction, including for commercial *
*  use.  (Attribution is not required but is appreciated.)               * 
*                                                                        *
*   David J. Eck                                                         *
*   Department of Mathematics and Computer Science                       *
*   Hobart and William Smith Colleges                                    *
*   Geneva, New York 14456,   USA                                        *
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
*                                                                        *
*************************************************************************/

// Draws the graph of a function and its first derivative (and optionally
// its second derivative).  It shows the tangent line to the graph and
// marks the corresponding point on the graph of the derivative.  The
// user controls the position of the tangent line with a slider and/or
// a number-input box.  A formula for the derivative can be displayed 
// at the bototm of the applet.
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;

public class Derivatives extends GenericGraphApplet {
   private String functionName;  // name of the fuction beging graphed, "f" by default; used in labels etc
   private Function func;   // The function that is graphed.
   private Function deriv;         // derivative of func
   private Expression derivExpression;  // The Expression that defines the derivative
   private Function deriv2;        // if non-null, second derivative of func
   private Controller subController = new Controller();  // Respond to changes in x-coord input; won"t redraw graph
   private VariableInput xInput; // x-coord of point of tangency
   
   private class ExprLbl extends Label implements Computable {
          // A class for displaying the formula for deriv
      String label;
      ExprLbl(String label) {
         this.label = label;
         compute();
      }
      public void compute() {
         setText(label + derivExpression.toString());
      }
   }
   
   protected void setUpParameterDefaults() { // I don"t want to use abs(x)^x as the default function, since it"s derivative is so funny
      parameterDefaults = new java.util.Hashtable();
      parameterDefaults.put("Function", " tan(" + getParameter("Variable","x") + ")");
   }
   
   protected void setUpMainPanel() {  // add a bunch of extra components at the end
      super.setUpMainPanel();
      
      // now that limitsPanel has been set up, add the two extra coordinate rects to it
      
      if (limitsPanel != null) {
         limitsPanel.addCoords(canvas.getCoordinateRect(1));  
         if (deriv2 != null)
            limitsPanel.addCoords(canvas.getCoordinateRect(2));  
      }
      else {  // CoordinateRects must synchronize with each other
         Tie coordTie = new Tie(canvas.getCoordinateRect(0),canvas.getCoordinateRect(1));
         if (deriv2 != null)
            coordTie.add(canvas.getCoordinateRect(2));
         canvas.getCoordinateRect(0).setSyncWith(coordTie);
         canvas.getCoordinateRect(1).setSyncWith(coordTie);
         if (deriv2 != null)
            canvas.getCoordinateRect(2).setSyncWith(coordTie);
      }
      
      
      // Add controls at the bottom of the panel for setting the value of x.
      // Also add the derivative formula, if it"s supposed to be displayed
   
      Value xMin = canvas.getCoordinateRect().getValueObject(CoordinateRect.XMIN);
      Value xMax = canvas.getCoordinateRect().getValueObject(CoordinateRect.XMAX);
      canvas.getCoordinateRect().setOnChange(subController);
      VariableSlider xSlider = new VariableSlider(xMin,xMax);
      xSlider.setOnUserAction(subController);
      xInput.setOnTextChange(subController);
      subController.add(xSlider);
      subController.add(xInput);
      subController.add( new Tie(xSlider,xInput) );
      
      Panel p = new Panel();
      p.setLayout(new BorderLayout(5,5));
      p.add(xInput.withLabel(), BorderLayout.WEST);
      p.add(xSlider, BorderLayout.CENTER);
      
      // If there is no limits panel, make it possible to add a RestoreLimits button to the input panel
      
      if (limitsPanel == null && ! "no".equalsIgnoreCase(getParameter("UseRestoreButton","no"))) {
               // add button to left of slider
           Button res = new Button("Restore Limits");
           p.add(res, BorderLayout.EAST);
           res.setBackground(Color.lightGray);
           res.addActionListener( new ActionListener() {
                   public void actionPerformed(ActionEvent evt) {
                      canvas.getCoordinateRect(0).restore();
                      canvas.getCoordinateRect(1).restore();
                      if (deriv2  != null) 
                         canvas.getCoordinateRect(2).restore();
                   }
              });
      }
      if ("yes".equalsIgnoreCase(getParameter("ShowFormula", "yes"))) { // add derivative formula
         Panel s = new Panel();
         s.setLayout(new GridLayout(2,1,3,3));
         s.add(p);
         ExprLbl lbl = new ExprLbl(" " + functionName + ""(" + xVar.getName() + ") = ");
         mainController.add(lbl);
         s.add(lbl);
         p = s;
      }
      
      if (inputPanel == null) {
            // Add the control panel directly to the main panel
         p.setBackground(getColorParam("PanelBackground",Color.lightGray));
         mainPanel.add(p,BorderLayout.SOUTH);
      }
      else {
            // Add control panel to bottom of input panel.
         inputPanel.add(p,BorderLayout.SOUTH);
      }
      
   } // end setUpMainPanel

   protected void setUpCanvas() {  // Override this to add more stuff to the canvas.
                                   // I don"t call super.setUpCanvas(), since
                                   // the canvas in this case is quite a bit different
                                   // from the standard one.
      boolean showSecond = ! "no".equalsIgnoreCase(getParameter("SecondDerivative","no"));
      xInput = new VariableInput(xVar.getName(), getParameter("X","1"));
      
      if (functionInput != null) {
         func = functionInput.getFunction(xVar);
         derivExpression = functionInput.getExpression().derivative(xVar);
      }
      else {
         String def = getParameter("Function");
         Expression exp = parser.parse(def);
         Function f = new SimpleFunction( exp, xVar );
         derivExpression = exp.derivative(xVar);
         func = new WrapperFunction(f);
      }
      Graph1D graph = new Graph1D(func);
      Color color = getColorParam("GraphColor",Color.black);
      graph.setColor(color);
      deriv = func.derivative(1);
      Graph1D derivGraph = new Graph1D(deriv);
      derivGraph.setColor(color);
      Graph1D deriv2Graph = null;
      if (showSecond) {
         deriv2 = deriv.derivative(1);
         deriv2Graph = new Graph1D(deriv2);
         deriv2Graph.setColor(color);
      }
      // Set up 2 or 3 coordinate retcs
      
      if (showSecond) {
         canvas.addNewCoordinateRect(0, 1.0/3.0, 0, 1);
         canvas.addNewCoordinateRect(1.0/3.0, 2.0/3.0, 0, 1);
         canvas.addNewCoordinateRect(2.0/3.0, 1, 0, 1);
      }
      else {
         canvas.addNewCoordinateRect(0, 0.5, 0, 1);
         canvas.addNewCoordinateRect(0.5, 1, 0, 1);
      }
      // do the type of stuff that"s usually done in super.setUpCanvas
      
      color = getColorParam("CanvasColor");
      if (color != null)
         canvas.setBackground(color);
      if (! "no".equalsIgnoreCase(getParameter("UsePanner", "no")) ) {
         canvas.add(new Panner(),0);
         canvas.add(new Panner(),1);
         if (showSecond)
            canvas.add(new Panner(),2);
      }
      if ( ! "no".equalsIgnoreCase(getParameter("UseGrid", "no")) ) {
         Grid g = new Grid();
         color = getColorParam("GridColor");
         if (color != null)
            g.setColor(color);
         canvas.add(g,0);
         g = new Grid();
         color = getColorParam("GridColor");
         if (color != null)
            g.setColor(color);
         canvas.add(g,1);
         if (showSecond) {
            g = new Grid();
            color = getColorParam("GridColor");
            if (color != null)
               g.setColor(color);
            canvas.add(g,2);
         }
      }
      canvas.add(makeAxes(),0);
      canvas.add(makeAxes(),1);
      if (showSecond)
         canvas.add(makeAxes(),2);
      if ( ! "no".equalsIgnoreCase(getParameter("UseMouseZoom", "no")) )
         canvas.setHandleMouseZooms(true);
      if ( "yes".equalsIgnoreCase(getParameter("UseOffscreenCanvas", "yes")) )
         canvas.setUseOffscreenCanvas(true);
      mainController.setErrorReporter(canvas);
      mainPanel.add(canvas, BorderLayout.CENTER);
      
      // add graphs, tangent lines etc.
      
      canvas.add(graph,0);
      canvas.add(derivGraph,1);
      if (showSecond)
         canvas.add(deriv2Graph,2);
         
      Color tangentColor = getColorParam("TangentColor", Color.red);
      Color tangentColor2 = getColorParam("TangentColor2", new Color(0, 180, 0));
            
      mainController.remove(canvas);
      mainController.add(graph);
      mainController.add(derivGraph);
      if (showSecond)
         mainController.add(deriv2Graph);
      
      subController = new Controller();
      mainController.add(subController);
      
      TangentLine tan = new TangentLine(xInput, func);
      Crosshair cross = new Crosshair(xInput,deriv);
      tan.setColor(tangentColor);
      cross.setColor(tangentColor);
      canvas.add(tan, 0);
      canvas.add(cross, 1);
      subController.add(tan);
      subController.add(cross);
      
      if (showSecond) {
         tan = new TangentLine(xInput, deriv);
         cross = new Crosshair(xInput, deriv2);
         tan.setColor(tangentColor2);
         cross.setColor(tangentColor2);
         canvas.add(tan, 1);
         canvas.add(cross, 2);
         subController.add(tan);
         subController.add(cross);
      }
      functionName = getParameter("FunctionName", "f");
      String yName = getParameter("YName","y");
      Color textColor = getColorParam("TextColor",Color.black);
      Color bgColor = getColorParam("TextBackground",Color.white);
      DrawString str;
      
      if ("yes".equalsIgnoreCase(getParameter("ShowGraphLabels","yes"))) {
         str = new DrawString(yName + " = " + functionName + "(" + xVar.getName() + ")");
         str.setColor(textColor);
         str.setBackgroundColor(bgColor);
         str.setFrameWidth(1);
         canvas.add(str,0);
         str = new DrawString(yName + " = " + functionName + " " (" + xVar.getName() + ")");
         str.setColor(textColor);
         str.setBackgroundColor(bgColor);
         str.setFrameWidth(1);
         canvas.add(str,1);
         if (showSecond) {
             str = new DrawString(yName + " = " + functionName + " " " (" + xVar.getName() + ")");
             str.setColor(textColor);
             str.setBackgroundColor(bgColor);
             str.setFrameWidth(1);
             canvas.add(str,2);
         }
      }
      if ("yes".equalsIgnoreCase(getParameter("ShowValues","yes"))) {
          str = new DrawString(functionName + "(#) = #", DrawString.BOTTOM_LEFT, new Value[] { xInput, new ValueMath(func,xInput) });
          str.setColor(textColor);
          str.setBackgroundColor(bgColor);
          str.setFrameWidth(1);
          str.setNumSize(7);
          canvas.add(str,0);
          subController.add(str);
          str = new DrawString(functionName + " " (#) = #", DrawString.BOTTOM_LEFT, new Value[] { xInput, new ValueMath(deriv,xInput) });
          str.setColor(textColor);
          str.setBackgroundColor(bgColor);
          str.setFrameWidth(1);
          str.setNumSize(7);
          canvas.add(str,1);
          subController.add(str);
          if (showSecond) {
             str = new DrawString(functionName + " " " (#) = #", DrawString.BOTTOM_LEFT, new Value[] { xInput, new ValueMath(deriv2,xInput) });
             str.setColor(textColor);
             str.setBackgroundColor(bgColor);
             str.setFrameWidth(1);
             str.setNumSize(7);
             canvas.add(str,2);
             subController.add(str);
          }
      }
   } // end setUpCanvas()
   
   
   protected void addCanvasBorder() { // override to add the border to each coordinate rect, and make default width equal to 1
      int borderWidth;
      double[] bw = getNumericParam("BorderWidth");
      if (bw == null || bw.length == 0 || bw[0] > 25)
         borderWidth = 2;
      else
         borderWidth = (int)Math.round(bw[0]);
      if (borderWidth > 0) {
         canvas.add( new DrawBorder( getColorParam("BorderColor", Color.black), borderWidth  ), 0 );
         canvas.add( new DrawBorder( getColorParam("BorderColor", Color.black), borderWidth  ), 1 );
         if (deriv2 != null)
            canvas.add( new DrawBorder( getColorParam("BorderColor", Color.black), borderWidth  ), 2 );
      }
   }

   protected void doLoadExample(String example) {
         // This method is called when the user loads an example from the 
         // example menu (if there is one).  It overrides an empty method
         // in GenericGraphApplet.
         //   For the SecantTangent applet, the example string should contain
         // an expression that defines the function to be graphed.  This can optionally
         // be followed by a semicoloon and a list of four or five numbers.
         // The first four numbers give the x- and y-limits to be used for the
         // example.  If they are not present, then -5,5,-5,5 is used.  The
         // fifth number, if present, gives the x-coord where the tangent line
         // is drawn initially.
   
      int pos = example.indexOf(";");
      double[] limits = { -5,5,-5,5 };  // x- and y-limits to use
      
      if (pos > 0) { // get limits from example text
         String limitsText = example.substring(pos+1);
         example = example.substring(0,pos);
         StringTokenizer toks = new StringTokenizer(limitsText, " ,");
         if (toks.countTokens() >= 4) {
            for (int i = 0; i < 4; i++) {
               try {
                   Double d = new Double(toks.nextToken());
                   limits[i] = d.doubleValue();
               }
               catch (NumberFormatException e) {
               }
            }
            if (toks.countTokens() > 0) { // Get point for tangent line
               try {
                   Double d = new Double(toks.nextToken());
                   xInput.setVal( d.doubleValue() );
               }
               catch (NumberFormatException e) {
               }
            }
         }
      }
      
      // Set up the example data and recompute everything.
      if (functionInput != null) {
            // If there is a function input box, put the example text in it.
         functionInput.setText(example);
      }
      else { 
           // If there is no user input, set the function in the graph directly.
           // Also, in this case, func is a "WrapperFunction".  Set the
           // definition of that WrapperFunction to be the same as f
         try {
            Expression exp = parser.parse(example);
            derivExpression = exp.derivative(xVar);
            Function f = new SimpleFunction( exp, xVar );
            ((WrapperFunction)func).setFunction(f);
         }
         catch (ParseError e) {  
             // There should"t be parse error"s in the Web-page
             // author"s examples!  If there are, the function
             // just won"t change.
         }
      }
      CoordinateRect coords = canvas.getCoordinateRect(0);
      coords.setLimits(limits);
      coords.setRestoreBuffer();
      canvas.getCoordinateRect(1).setRestoreBuffer();
      if (deriv2 != null)
         canvas.getCoordinateRect(0).setRestoreBuffer();
      mainController.rupute();
      
   } // end doLoadExample()
   
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new Derivatives();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }   

} // end class SimpleGraph





Display the graph of a single function of one variable

/*************************************************************************
*                                                                        *
*  This source code file, and compiled classes derived from it, can      *
*  be used and distributed without restriction, including for commercial *
*  use.  (Attribution is not required but is appreciated.)               * 
*                                                                        *
*   David J. Eck                                                         *
*   Department of Mathematics and Computer Science                       *
*   Hobart and William Smith Colleges                                    *
*   Geneva, New York 14456,   USA                                        *
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
*                                                                        *
*************************************************************************/

// The SimpleGraph applet is a configurable applet that displays the graph of
// a single function of one variable.  Optionally, a point can be marked on
// the graph.  The user can control the location of the point.
import java.awt.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;

public class SimpleGraph extends GenericGraphApplet {
   // Declare some private variables that are created in one method in
   // this class and used in a second method.
   private VariableInput xInput; // Contains the x-coordinate of the marked point.
   private Function func;   // The function that is graphed.
   private Graph1D graph;   // The graph of the function.
   private DrawGeometric point;  // An oval that marks the selected point on the graph.
   private DrawGeometric vLine;  // A line from the point to the x-axis.
   private DrawGeometric hLine;  // A line from the point to the y-axis.

   protected void setUpCanvas() {  // Override this to add more stuff to the canvas.
   
      super.setUpCanvas();  // Do the common setup: Add the axes and
      // When setUpCanvas is called, the functionInput already exists, if one is
      // to be used, since it is created in setUpBopttomPanel(), which is called
      // before setUpCanvas.  If functionInput exists, add a graph of the function
      // from functionInput to the canvas.  If not, create a graph of the function
      // specified by the parameter named "Function".
      
      if (functionInput != null)
         func = functionInput.getFunction(xVar);
      else {
         String def = getParameter("Function", " abs(" + xVar.getName() + ") ^ " + xVar.getName());
         Function f = new SimpleFunction( parser.parse(def), xVar );
         func = new WrapperFunction(f);
      }
      graph = new Graph1D(func);
      Color color = getColorParam("GraphColor");
      if (color != null)
         graph.setColor(color);
         
      // If the applet is configured to mark a point on the graph, create the point and
      // the lines from the point to the x- and y-axes and add them to the canvas before
      // the graph.  The properties of these objects have to be set later, in setUpMainPanel(),
      // because the input objects that they depend on don"t exist when this method is
      // called.  However, I want to add them to the canvas here so they will lie behind the
      // graph and behind the border of the canvas (which is added after setUpCanvas() is
      // executed).
      if (! "no".equalsIgnoreCase( getParameter("ShowPoint","yes") ) ) {
         vLine = new DrawGeometric();
         hLine = new DrawGeometric();
         point = new DrawGeometric();
         canvas.add(vLine);
         canvas.add(hLine);
         canvas.add(point);
      }
      canvas.add(graph);  // Finally, add the graph to the canvas.
   } // end setUpCanvas()
   
   
   protected void setUpMainPanel() { // Override to handle the point marked on the graph
   
      super.setUpMainPanel(); // Do the common setup
      if ( "no".equalsIgnoreCase( getParameter("ShowPoint","yes") ) ) {
         return;  // If the applet is not configured to show a point, there is nothing to do.
      }
      
      // Create two input objects, a VariableInput and a VariableSlider.  The values of
      // the two inputs will be synchronized with each other using a "Tie".  The
      // minimum and maximum values represented on the slider are given by the
      // the minimum and maximum x-coordinates on the CoordinateRect.  This will restrict
      // the x-coodinate of the point that is marked on the graph to the range of 
      // x-values actually shown on the screen.
      
      xInput = new VariableInput();   // An input box for the x-coord of the marked point
      xInput.setInputStyle(VariableInput.REAL);   // Allow only real numbers (not constant expressions)
      CoordinateRect coords = canvas.getCoordinateRect();
      VariableSlider xSlider = new VariableSlider( coords.getValueObject(CoordinateRect.XMIN), 
                                                      coords.getValueObject(CoordinateRect.XMAX) );
      
      Value yValue = new ValueMath(func,xSlider); // Represents the y-value of the marked point.
      
      DisplayLabel yDisplay = new DisplayLabel(" y = #", yValue);  // Shows the y-value of the point
      
      // Create a panel to contain the input objects.
      
      JCMPanel panel = new JCMPanel(1,3);
      panel.setBackground(getColorParam("PanelBackground",Color.lightGray));
      JCMPanel subpanel = new JCMPanel();
      String varName = getParameter("Variable","x");
      subpanel.add(new Label(" " + varName + " = ", Label.CENTER), BorderLayout.WEST);
      subpanel.add(xInput, BorderLayout.CENTER);
      panel.add(xSlider);
      panel.add(subpanel);
      panel.add(yDisplay);
      
      // If there is a functionInput box, then the SOUTH position of the mainPanel already contains
      // the inputPanel that contains that box.  If so, add the new panel to the SOUTH position of
      // the inputPanel.  (This is a good place, in general, to put extra input objects.)
      // If there is no inputPanel, then the SOUTH position of the mainPanel is empty, so put
      // the newly created panel there.  Also, set the background color for the input panel from
      // from the PanelBackground applet param.  (This is already done for inputPanel, if it exists.)
      
      if (inputPanel == null)
         mainPanel.add(panel, BorderLayout.SOUTH);
      else {
         inputPanel.setBackground(getColorParam("PanelBackground",Color.lightGray));
         inputPanel.add(panel, BorderLayout.SOUTH);
      }
      // Set up all the data for the point and the lines from the point to the axes.
      // The objects where created in setUpCanvas() and added to the canvas.
      hLine.setPoints(new Constant(0),yValue,xSlider,yValue);
      hLine.setPoints(new Constant(0),yValue,xSlider,yValue);
      point.setShape(DrawGeometric.CROSS);
      point.setPoints(xSlider,yValue,5,5);
      point.setLineWidth(3);
      vLine.setPoints(xSlider,new Constant(0),xSlider,yValue);
      Color c = getColorParam("LineColor", Color.lightGray);
      vLine.setColor(c);
      hLine.setColor(c);
      c = getColorParam("DotColor", Color.gray);
      point.setColor(c);
      // Now, I have to set a Controller to respond to changes in the input objects.
      // I could just use the mainController, but then the data for the graph would
      // be recomputed whenever the user changes the x-coordinate of the marked point.
      // For effieciency, I will use a separate Controller that only recomputes the
      // data for the point (not the graph) when the inputs change.
      
      Controller cc = new Controller();
      xInput.setOnTextChange(cc);   // cc responds when user types in the input box
      xSlider.setOnUserAction(cc);  // cc responds when the user drags the slider
      coords.setOnChange(cc);       // cc responds when the coordinate limits change;
                                    //    this is necessary because the minimum and
                                    //    maximum values on the slider have to be checked.
      cc.add( xInput );  // Check whether the values have changed.
      cc.add( xSlider );
      cc.add( new Tie(xSlider,xInput) );  // synchronize values of input box and slider
      cc.add( hLine );  // Recompute the values for the point and lines.
      cc.add( vLine );
      cc.add( point );
      cc.add( yDisplay ); // Recompute the value displayed on the yDisplay label.
      mainController.add(cc);  // When the mainController recomputes (because function has
                               //   been changed, all the stuff controlled by cc also has
                               //   to be checked.
      
      mainController.remove(canvas);  // The mainController should not recompute the contents
                                      //   of the canvas (which it would do by default).
      mainController.add(graph);      // But the mainController should recompute the graph.
   } // end setUpMainPanel()
   

   protected void doLoadExample(String example) {
         // This method is called when the user loads an example from the 
         // example menu (if there is one).  It overrides an empty method
         // in GenericGraphApplet.
         //   For the SimpleGraph applet, the example string should contain
         // an expression that defines the function to be graphed.  This can optionally
         // be followed by a semicoloon and a list of four or five numbers.
         // The first four numbers give the x- and y-limits to be used for the
         // example.  If they are not present, then -5,5,-5,5 is used.  The
         // fifth number, if present, gives the x-coord of the marked point
         // on the graph.
   
      int pos = example.indexOf(";");
      double[] limits = { -5,5,-5,5 };  // x- and y-limits to use
      
      if (pos > 0) { // get limits from example text
         String limitsText = example.substring(pos+1);
         example = example.substring(0,pos);
         StringTokenizer toks = new StringTokenizer(limitsText, " ,");
         if (toks.countTokens() >= 4) {
            for (int i = 0; i < 4; i++) {
               try {
                   Double d = new Double(toks.nextToken());
                   limits[i] = d.doubleValue();
               }
               catch (NumberFormatException e) {
               }
            }
            if (toks.countTokens() > 0 && xInput != null) {
                  // get x-coord of marked point from example text
               try {
                   Double d = new Double(toks.nextToken());
                   xInput.setVal( d.doubleValue() );
               }
               catch (NumberFormatException e) {
               }
            }
         }
      }
      
      // Set up the example data and recompute everything.
      if (functionInput != null) {
            // If there is a function input box, put the example text in it.
         functionInput.setText(example);
      }
      else { 
           // If there is no user input, set the function in the graph directly.
           // Also, in this case, func is a "WrapperFunction".  Set the
           // definition of that WrapperFunction to be the same as f
         try {
            Function f = new SimpleFunction( parser.parse(example), xVar );
            ((WrapperFunction)func).setFunction(f);
         }
         catch (ParseError e) {  
             // There should"t be parse error"s in the Web-page
             // author"s examples!  If there are, the function
             // just won"t change.
         }
      }
      CoordinateRect coords = canvas.getCoordinateRect(0);
      coords.setLimits(limits);
      coords.setRestoreBuffer();
      mainController.rupute();
      
   } // end doLoadExample()
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         java.applet.Applet app = new SimpleGraph();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }   

} // end class SimpleGraph





Draw Math Function In Coordinate

import java.awt.*;
import java.applet.*;
import java.net.URL;
import graph.*;
/*************************************************************************
**
**    Applet example1
**                                              Version 1.0   January 1996
**
**************************************************************************
**    Copyright (C) 1996 Leigh Brookshaw
**
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation; either version 2 of the License, or
**    (at your option) any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************
**
**    This is a simple applet that demonstrates how to use the basic features
**    of the Plotting Class library. The data is calculated locally by
**    the applet
**
*************************************************************************/
public class example1 extends Applet {
      Graph2D graph;
      DataSet data1;
      DataSet data2;
      Axis    xaxis;
      Axis    yaxis_left;
      Axis    yaxis_right;
      double data[];
      int np = 100;
      URL markerURL;

      public void init() {
        int i;
        int j;
        double data[] = new double[2*np];
/*
**      Get the passed parameters
*/
        String mfile    = "marker.txt";
/*
**      Create the Graph instance and modify the default behaviour
*/
        graph = new Graph2D();
        graph.drawzero = false;
        graph.drawgrid = false;
        graph.borderTop = 50;
/*
**      Load a file containing Marker definitions
*/
        try {
           //markerURL = this.getClass().(mfile);
           markerURL = this.getClass().getResource(mfile);
           graph.setMarkers(new Markers(markerURL));
        } catch(Exception e) {
           System.out.println("Failed to create Marker URL!");
        }

        setLayout( new BorderLayout() );
        add("Center", graph);
/*
**      Calculate the first data Set.
*/
        for(i=j=0; i<np; i++,j+=2) {
            data[j] = j-np;
            data[j+1] = 60000 * Math.pow( ((double)data[j]/(np-2) ), 2);
        }
        data1 = graph.loadDataSet(data,np);
        data1.linestyle = 0;
        data1.marker    = 1;
        data1.markerscale = 1.5;
        data1.markercolor = new Color(0,0,255);
        data1.legend(200,100,"y=6x10{^4}x^2");
        data1.legendColor(Color.black);
/*
**      Calculate the Second data Set.
*/
        for(i=j=0; i<np; i++,j+=2) {
            data[j] = j-np;
            data[j+1] = Math.pow( ((double)data[j]/(np-2) ), 3);
        }
        data2 = graph.loadDataSet(data, np);
        data2.linecolor   =  new Color(0,255,0);
        data2.marker      = 3;
        data2.markercolor = new Color(100,100,255);
        data2.legend(200,120,"y=x^3");
        data2.legendColor(Color.black);
/*
**      Attach both data sets to the Xaxis
*/
        xaxis = graph.createAxis(Axis.BOTTOM);
        xaxis.attachDataSet(data1);
        xaxis.attachDataSet(data2);
        xaxis.setTitleText("Xaxis");
        xaxis.setTitleFont(new Font("TimesRoman",Font.PLAIN,20));
        xaxis.setLabelFont(new Font("Helvetica",Font.PLAIN,15));
/*
**      Attach the first data set to the Left Axis
*/
        yaxis_left = graph.createAxis(Axis.LEFT);
        yaxis_left.attachDataSet(data1);
        yaxis_left.setTitleText("y=6x10{^4}x^2");
        yaxis_left.setTitleFont(new Font("TimesRoman",Font.PLAIN,20));
        yaxis_left.setLabelFont(new Font("Helvetica",Font.PLAIN,15));
        yaxis_left.setTitleColor( new Color(0,0,255) );
/*
**      Attach the second data set to the Right Axis
*/
        yaxis_right = graph.createAxis(Axis.RIGHT);
        yaxis_right.attachDataSet(data2);
        yaxis_right.setTitleText("y=x^3");
        yaxis_right.setTitleFont(new Font("TimesRoman",Font.PLAIN,20));
        yaxis_right.setLabelFont(new Font("Helvetica",Font.PLAIN,15));
        yaxis_right.setTitleColor(new Color(100,100,255) );
      }
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new example1();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }
}





Draw math function on the coordinate

/*************************************************************************
*                                                                        *
*  This source code file, and compiled classes derived from it, can      *
*  be used and distributed without restriction, including for commercial *
*  use.  (Attribution is not required but is appreciated.)               * 
*                                                                        *
*   David J. Eck                                                         *
*   Department of Mathematics and Computer Science                       *
*   Hobart and William Smith Colleges                                    *
*   Geneva, New York 14456,   USA                                        *
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
*                                                                        *
*************************************************************************/
import java.awt.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.awt.*;
public class GraphApplet2 extends java.applet.Applet {
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         java.applet.Applet app = new GraphApplet2();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }  
   private DisplayCanvas canvas;
   
   public void stop() {
         // To be a little nicer to the system, I have declared the DisplayCanvas
         // outside the init() method, and I use the standard stop() method of
         // the applet to call canvas.releaseResources().  This frees up the
         // substantial amount of memory that is used for the off-screen copy
         // of image displayed on the canvas.  (This off-screen copy is used for
         // "double-buffering".)
      canvas.releaseResources();
   }
   
   public void init() {
   
      Parser parser = new Parser();      // Create the parser and the variable, x.
      Variable x = new Variable("x");
      parser.add(x);
      canvas = new DisplayCanvas();      // Create the canvas, and set it to do zooming.
      canvas.setHandleMouseZooms(true);
      
      canvas.add(new Panner());  // Adding a panner lets the user right-click-and-drag on the
                                 // canvas to slide the graph around.
      
      CoordinateRect coords = canvas.getCoordinateRect();
          // Behind the scene, a canvas has a CoordinateRect, which actually keeps track
          //   of the x- and y-limits (and does some of the other work of the canvas).
          //   For some purposes, you need the CoordinateRect.  You can obtain it by
          //   calling the DisplayCanvas"s getCoordinateRect() method.
      
      LimitControlPanel limits =
           new LimitControlPanel( LimitControlPanel.SET_LIMITS | LimitControlPanel.RESTORE, false);
             // In this case, I am using a LimitControlPanel that contains two buttons.
             //   the usual "Set Limits" button and a "Restore Limits" button.  The second button
             //   button will restore the original limits on the canvas.  The second parameter
             //   to this constructor can be set to true if you would like the components in the
             //   LimitControlPanel to be arranged into two columns instead of one.
             //   Buttons can also be added after the constructor is called by calling
             //   the addButtons() method from class LimitControlPanel.
      limits.addCoords(canvas);
      
      ExpressionInput input = new ExpressionInput("sin(x)+2*cos(3*x)", parser);  // For user input
      Function func = input.getFunction(x);  // The function that will be graphed.
      Graph1D graph = new Graph1D(func);     // The graph itself.
      
      VariableInput xInput = new VariableInput();  // An input box where the user can
                                                   //   specify the x-coordinate of the
                                                   //   point on the graph that is marked 
                                                   //   by the crosshair.  
      
      VariableSlider xSlider = new VariableSlider( coords.getValueObject(CoordinateRect.XMIN), 
                                            coords.getValueObject(CoordinateRect.XMAX) );
          // A VariableSlider is a slider (actually a Scrollbar) that the user can
          //   adjust as a means of inputting a value.  The parameters to the constructor
          //   specify the minimum and maximum of this value.  In this case, the minimum
          //   value is coords.getValueObject(CoordinateRect.XMIN).  This says that the
          //   minimum value on the slider is given by the minimum x-value on the canvas"s
          //   CoordinateRect.  This minimum is adjusted automatically when the limits
          //   on the CoordinateRect change.  The maximum value is similar.
          // This Variable Slider is actually used as a second way of inputting the
          //   x-coordinate of the point where the crosshair is shown.  Later, the value of
          //   the slider will be "tied" to the value in the VariableInput.  You should check
          //   that when you change one, the other is also changed.  (To change the
          //   value associated with the VariableInput box, you have to press return
          //   in that box.)
      
      DrawString info = new DrawString("x = #\nf(x) = #", DrawString.TOP_LEFT,
                                   new Value[] { xSlider, new ValueMath(func,xSlider) });
          // A DrawString draws a string on a DisplayCanvas.  The string can have line
          //   breaks, indicated by "\n", and can contain embedded Values, indicated
          //   by "#".  The position of the string is DrawString.TOP_LEFT.  That is,
          //   it is in the top-left corner of the canvas.  The third parameter is
          //   an array of Value objects whose values are substituted for the #"s
          //   in the string.
          
      info.setFont( new Font("SansSerif",Font.BOLD,12) );  // Set properties of the DrawString.
      info.setColor( new Color(0,100,0) );
      info.setOffset(10);
      
      ComputeButton graphIt = new ComputeButton("Graph It!");
          // A ComputeButton is just a button that can be registered with a Controller,
          //   so that clicking on the Button causes the Controller to compute.  In this
          //   case, this is a redundant input, since pressing return in the ExpressionInput
          //   box will accomplish the same thing.  However, the button gives the user
          //   a more obvious way to change the function that is graphed.
      
      JCMPanel main = new JCMPanel();         // The interface is constructed of JCMPanels.
      JCMPanel top = new JCMPanel();          
      JCMPanel bottom = new JCMPanel();
      main.add(canvas, BorderLayout.CENTER);
      main.add(limits, BorderLayout.EAST);
      main.add(bottom, BorderLayout.SOUTH);
      main.add(top, BorderLayout.NORTH);
      main.setInsetGap(3);
      top.add(input, BorderLayout.CENTER);
      top.add(new Label(" f(x) = "), BorderLayout.WEST);
      top.add(graphIt, BorderLayout.EAST);
      
      bottom.add(xSlider, BorderLayout.CENTER);
      bottom.add(xInput, BorderLayout.EAST);
      bottom.add(new Label("  x = "), BorderLayout.WEST);
      setLayout(new BorderLayout());   // Set up for the Applet itself.
      add(main, BorderLayout.CENTER);
      setBackground(Color.lightGray);      
      
      canvas.add( new Axes() );  // Add a set of axes to the DisplayCanvas.
      canvas.add(graph);         // Add the graph of the function to the DisplayCanvas.
      canvas.add( new Crosshair(xSlider, func) );  // Add a CrossHair to the canvas.
                                                   //   The crosshair is on the graph of the
                                                   //   function, func, at the point whose xCoordinate
                                                   //   is given by the value on the slider, xSlider.
      canvas.add( info );  // Add the DrawString to the canvas.
      canvas.add( new DrawBorder(Color.darkGray, 2) );  // Add a 2-pixel dark gray border around
                                                        //   edges of the canvas.
      
      main.gatherInputs();  // The Controller for the main panel.
                            //    must be set to respond to user actions
                            //    on the input objects.  The gatherInputs()
                            //    method is an easy way to do this.  This calls
                            //    the setOnUserAction() method of the four
                            //    input objects:  input, graphIt, xInput
                            //    and xSlider.
      
      Controller controller = main.getController();  // Get the controller from the main panel.
                                                     // We still need it for a few things...
                                                     
      graphIt.setOnUserAction(controller);  // ComputeButtons aren"t handled automatically
                                            //   by main.gatherInput().  It must be set
                                            //   to notify the controller when it is clicked,
                                            //   in order for the applet to be recomputed
                                            //   when the button is clicked.
      coords.setOnChange(controller);   // Because the VariableSlider depends on the limits
                                        //   on the CoordinateRect, the controller must also
                                        //   listen for changes in these limits.  The gatherInputs()
                                        //   doesn"t "gather" in the coordinate rect.      
                                        
      controller.add( new Tie(xSlider,xInput) );  // This is the thing that synchronizes the
                                                  //   values on the VariableSlider and the
                                                  //   VariableSlider.  After checking all the
                                                  //   inputs in the applet, the Controller
                                                  //   "synchronizes" the two objects named
                                                  //   in the "Tie".
      
      // I forgot to set an errorReporter for this applet!
      // You can check what happens when the input in the applet
      // contains an error. (The error message is printed to
      // standard output.  In Netscape, for example, this means
      // that it goes to the Java Console, where it will do the
      // user no good at all.)
 
   }  // end init()
} // end class SimpleGraph





Draw Math Function Your Own

import java.awt.*;
import java.applet.*;
import graph.*;
/*
**************************************************************************
**
**                      Applet parse1d
**
**************************************************************************
**    Copyright (C) 1995, 1996 Leigh Brookshaw
**
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation; either version 2 of the License, or
**    (at your option) any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************
*
* This applet uses the ParseFunction class to parse an input string
* and plot the result.
*
*************************************************************************/
public class parse1d extends Applet {
      G2Dint graph         = new G2Dint();   // Graph class to do the plotting
      Axis xaxis;
      Axis yaxis;
      DataSet data;
      TextField pinput     = new TextField(5);       // Number of points 
      TextField mininput   = new TextField(10);      // Minimum x value input
      TextField maxinput   = new TextField(10);      // Maximum x value input
      TextField finput     = new TextField(30);      // Input for the function to plot
      Button plot          = new Button("Plot It!"); // Button to plot it.


      public void init() {
         Label title            = new Label("Function Parsing",Label.CENTER);
         Panel panel            = new Panel();
         GridBagLayout gridbag  = new GridBagLayout();
         GridBagConstraints  c  = new GridBagConstraints();
         Font font              = new Font("TimesRoman",Font.PLAIN,15);
         title.setFont(new Font("TimesRoman",Font.PLAIN,25));
          
         
         setLayout(new BorderLayout() );
         add("North",title);
         add("Center",panel);
         finput.setText("sin(x)"); 
         pinput.setText("1000"); 
         mininput.setText("0"); 
         maxinput.setText("20"); 

         
         
         panel.setLayout(gridbag);
         Label plabel   = new Label("Number of Points");         
         Label minlabel = new Label("Minimum x Value");
         Label maxlabel = new Label("Maximum x Value");
         Label flabel   = new Label("Function");
         
         plabel.setFont(font);
         flabel.setFont(font);
         minlabel.setFont(font);
         maxlabel.setFont(font);
         
         pinput.setFont(font);
         pinput.setBackground(Color.lightGray);
         finput.setFont(font);
         finput.setBackground(Color.lightGray);
         mininput.setFont(font);
         mininput.setBackground(Color.lightGray);
         maxinput.setFont(font);
         maxinput.setBackground(Color.lightGray);
         plot.setFont(font);
         plot.setBackground(Color.green);
         c.weightx = 1.0;
         c.weighty = 1.0;
         c.gridwidth = 3;
         c.gridwidth=GridBagConstraints.REMAINDER;
         c.fill  =  GridBagConstraints.BOTH;
         
         gridbag.setConstraints(graph,c);
         
         c.fill  =  GridBagConstraints.NONE;
         c.weightx=0.0;
         c.weighty=0.0;
         c.gridheight=1;
         
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(flabel,c);
         
         c.anchor = GridBagConstraints.CENTER;
         c.gridwidth=GridBagConstraints.RELATIVE;
         c.fill  =  GridBagConstraints.HORIZONTAL;
         gridbag.setConstraints(finput,c);
         
         c.fill = GridBagConstraints.NONE;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(plot,c);
         
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(plabel,c);
         c.gridwidth=2;
         c.anchor = GridBagConstraints.WEST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(pinput,c);
         
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(minlabel,c);
         c.gridwidth=2;
         c.anchor = GridBagConstraints.WEST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(mininput,c);
         
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(maxlabel,c);
         c.gridwidth=2;
         c.anchor = GridBagConstraints.WEST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(maxinput,c);
         
         
         panel.add(graph);
         panel.add(flabel);
         panel.add(finput);
         panel.add(plot);
         panel.add(plabel);
         panel.add(pinput);
         panel.add(minlabel);
         panel.add(mininput);
         panel.add(maxlabel);
         panel.add(maxinput);
         
         xaxis = graph.createXAxis();
         xaxis.setTitleText("X");
         yaxis = graph.createYAxis();

         data = new DataSet();
         xaxis.attachDataSet(data);
         yaxis.attachDataSet(data);
         graph.attachDataSet(data);

         graph.setDataBackground(new Color(255,200,175));
         graph.setBackground(new Color(200,150,100));
         plot();
      }

      void plot() {
         int points;
         double maximum;
         double minimum;
         double x;
         int count = 0;
         boolean error = false;
         try {
              points   = Integer.parseInt(pinput.getText());
         } catch(Exception e) {
//              this.showStatus("Error with number of points!");
              System.out.println("Number of points error "+e.getMessage());
              return;
         }
         try {
            maximum = Double.valueOf(maxinput.getText()).doubleValue();
         } catch(Exception e) {
  //            this.showStatus("Error with X maximum value!");
              System.out.println("X maximum error "+e.getMessage());
              return;
         }
         try {
            minimum = Double.valueOf(mininput.getText()).doubleValue();
         } catch(Exception e) {
    //          this.showStatus("Error with X minimum value!");
              System.out.println("X minimum error "+e.getMessage());
              return;
         }
         ParseFunction function = new ParseFunction(finput.getText());
         if(!function.parse()) {
      //        this.showStatus("Failed to parse function!");
              System.out.println("Failed to parse function!");
              return;
         }
         double d[] = new double[2*points];
        // this.showStatus("Calculating points!");
         for(int i=0; i<points; i++) {
             x = minimum + i*(maximum-minimum)/(points-1);
             d[count] = x;
             try {
                  d[count+1] = function.getResult(x);
                  count += 2;
             } catch(Exception e) { error = true; }
         }
 
         if(count <= 2) {
//             this.showStatus("Error NO POINTS to PLOT!"); 
             System.out.println("Error NO POINTS to PLOT!");
             return;
         } else
         if( error ) {
  //           this.showStatus("Error while Calculating points!"); 
             System.out.println("Error while calculating points!");
   }

         yaxis.setTitleText(finput.getText());
         data.deleteData();
         try {
               data.append(d,count/2);
         } catch(Exception e) {
    //         this.showStatus("Error while appending data!"); 
             System.out.println("Error while appending data!");
             return;
   }
              
         graph.repaint();
      }

     public boolean action(Event e, Object a) {
         if(e.target instanceof Button) {
             if( plot.equals(e.target) ) {
                  plot();
                  return true;
             }
         }

         return false;
       }

      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new parse1d();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }
}





Draw the function

/*************************************************************************
*                                                                        *
*  This source code file, and compiled classes derived from it, can      *
*  be used and distributed without restriction, including for commercial *
*  use.  (Attribution is not required but is appreciated.)               * 
*                                                                        *
*   David J. Eck                                                         *
*   Department of Mathematics and Computer Science                       *
*   Hobart and William Smith Colleges                                    *
*   Geneva, New York 14456,   USA                                        *
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
*                                                                        *
*************************************************************************/

import java.awt.*;
import java.applet.Applet;
import java.util.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;
// The MultiApplet can display the graphs of several functions, in different colors.
// By default, there is only one function, but you can configure the applet to
// use more than one function with applet params.
// The definitions of these functions can, optionally, use parameters whose
// values are controled by sliders at the bottom of the applet.  
public class MultiGraph extends GenericGraphApplet {

   private Vector sliders;  // Elements of this vector are the VariableSlider
                            //   objects that represent the parameter values.
                            //   The sliders are created in the setUpParser() method.
                            
   private ExprIn[] inputs;  // The function input boxes (or null if inputs aren"t used)
   private Graph1D[] graphs; // The graphs of the functions, in the case function input boxes are NOT used
   private int functionCt;   // Number of functions -- size of inputs or graphs array
   
   private Color[] graphColors = { Color.magenta, new Color(0,180,0), 
                           Color.red, new Color(0,200,200),
                           Color.orange, Color.gray, Color.blue, Color.pink };

   private static class ColorPatch extends Canvas { 
          // a canvas with a preferred size
      ColorPatch(Color c) {
         setBackground(c);
      }
      public Dimension getPreferredSize() {
         return new Dimension(25,10);
      }
      public void paint(Graphics g) {
         g.drawRect(0,0,getSize().width-1,getSize().height-1);
      }
   }
   
   private static class ExprIn extends ExpressionInput { 
            // Doesn"t throw an error if empty, just sets function in graph to null
      Graph1D graph;  // Graph associated with this function input.
      Function func;  // The function of x defined by this graph.
      ExprIn(String definition, Parser p, Graph1D g, Variable v) {
         super(definition,p);
         graph = g;
         func = getFunction(v);
         if (definition.trim().length() > 0)
            graph.setFunction(func);
      }
      public void checkInput() { // (will be called during constructor -- hence the funny bit with checking if graphe is null)
         boolean hasChanged = previousContents == null || !previousContents.equals(getText());
         if (!hasChanged)
            return;
         String text = getText().trim();
         if (text.length() == 0) {  // set graph"s function to null so it doesn"t have to do any computations.
            if (graph != null)
               graph.setFunction(null);
            previousContents = getText();
         }
         else {
            super.checkInput();
            if (graph != null)
               graph.setFunction(func);
         }
      }
   }
   protected void setUpParser() {  // Override this to add VariableSliders to parser.
   
      // Get the data for any sliders from applet params named "Parameter", "Parameter1", ...
      // The sliders are created and the variables are added to the parser by the
      // addParameter() method, which is defined below.
      
      sliders = new Vector();
      int ct = 0;
      String param = getParameter("Parameter");
      if (param == null) {
         ct++;
         param = getParameter("Parameter" + ct);
      }
      while (true) {
         if (param == null)
            break;
         addParameter(param);
         ct++;
         param = getParameter("Parameter" + ct);
      }
      
      super.setUpParser();  // Call this last so function definitions 
                            // in applet params can use the parameter names 
                                                        
   } // end setUpParser()
   

   private void addParameter(String data) {
         // Create a VariableSlider from the information in name and add it to the
         // Vector of sliders.  The data must contain the name of the variable 
         // associated with the slider.  The name can be followed by a ";" and up to
         // three numbers.  (If there is no ";", a space after the name will do.)
         // The numbers can be separated by commas, spaces, or tabs.  The first
         // number gives the minimum value on the slider, the second gives the maximum,
         // and the third gives the initial value of the slider variable.
      double min = -5, max = 5, val = 0;  // min, max, and value for slider
      data = data.trim();
      int pos = data.indexOf(";");
      if (pos < 0)
         pos = data.indexOf(" ");
         
      String name; //  The name of the parameter
      if (pos < 0) {
            // If there is no space or ";", the data is just the name of the variable.
         name = data;
      }
      else {
            // Get the name from the front of the data, then look for min, max, and val.
          String nums = data.substring(pos+1);
          name = data.substring(0,pos).trim();
          StringTokenizer toks = new StringTokenizer(nums," ,\t");
          try {
             if (toks.hasMoreElements())
                 min = (new Double(toks.nextToken())).doubleValue();
             if (toks.hasMoreElements())
                 max = (new Double(toks.nextToken())).doubleValue();
             if (toks.hasMoreElements())
                 val = (new Double(toks.nextToken())).doubleValue();
          }
          catch (NumberFormatException e) {
             min = -5;
             max = 5;
             val = 0;
          }
      }
      
      // Create the slider, adding the associated variable to the parser, and set its value.
      
      VariableSlider slide = new VariableSlider(name, new Constant(min), new Constant(max), parser);
      slide.setVal(val);
      
      sliders.addElement(slide);  // Save the slider in the array of sliders for later use.
      
   } // end setUpParser();
   
   
   private void getColors() { // get graph colors from color parameters, if any.
      
      Vector vec = new Vector();
      int ct = 0;
      Color c = getColorParam("GraphColor");
      if (c == null) {
         ct++;
         c = getColorParam("GraphColor" + ct);
      }
      while (true) {
         if (c == null)
            break;
         vec.addElement(c);
         ct++;
         c = getColorParam("GraphColor" + ct);
      }
      if (vec.size() > 0) {
         graphColors = new Color[vec.size()];
         for (int i = 0; i < vec.size(); i++)
            graphColors[i] = (Color)vec.elementAt(i);
      }
   }
   
   private Vector getFunctions() {  // Read applet parms "Function", "Funcion1", ...
                                    // Return a vector containing the function definition strings
      Vector functions = new Vector();
      int ct = 0;
      String c = getParameter("Function");
      if (c == null) {
         ct++;
         c = getParameter("Function" + ct);
      }
      while (true) {
         if (c == null)
            break;
         functions.addElement(c);
         ct++;
         c = getParameter("Function" + ct);
      }
      if (functions.size() == 0)
         functions.addElement( " abs( " + xVar.getName() + ") ^ " + xVar.getName() );
      double[] d = getNumericParam("FunctionCount");
      if (d == null || d.length == 0 || d[0] <= 0.5)
         functionCt = functions.size();
      else {
         functionCt = (int)Math.round(d[0]);
         if (functionCt < functions.size()) { // use number of functions specified as functionCt
            functionCt = functions.size();
         }
         else {  // make extra empty functions to bring total up to functionCt
            int extra = functionCt - functions.size();
            for (int i = 0; i < extra; i++)
               functions.addElement("");
         }
      }
      return functions;
   }
   
   private Panel makeFunctionInput(Vector functions, int funcNum) {  
           // make input box for specified function
           // also adds the input box to the inputs[] array
      Graph1D graph = new Graph1D();
      graph.setColor(graphColors[funcNum % graphColors.length]);
      ExprIn in = new ExprIn((String)functions.elementAt(funcNum),parser,graph,xVar);
      in.setOnUserAction(mainController);
      JCMPanel p = new JCMPanel();
      p.add(in,BorderLayout.CENTER);
      String name;
      if (functions.size() > 1)
         name = " " + getParameter("FunctionName","f") + (funcNum+1) + "(" + xVar.getName() + ") = ";
      else
         name = " " + getParameter("FunctionName","f") +  "(" + xVar.getName() + ") = ";
      p.add(new Label(name), BorderLayout.WEST);
      if (graphColors.length > 1 && functions.size() > 1)
         p.add(new ColorPatch( graphColors[funcNum % graphColors.length] ), BorderLayout.EAST);
      inputs[funcNum] = in;
      return p;
   }

   protected void setUpBottomPanel() {  
      // Overridden to create an appropriate input panel
      // Create a panel holding all the function inputs and
      // sliders, with a display label for each slider to show its value.
      
      boolean funcInput = "yes".equalsIgnoreCase(getParameter("UseFunctionInput","yes"));
      
      if ( funcInput && "yes".equalsIgnoreCase(getParameter("UseComputeButton", "yes")) ) { // make the compute button
         String cname = getParameter("ComputeButtonName", "New Functions");
         computeButton = new Button(cname);
         computeButton.addActionListener(this);
      }
      Panel firstPanel = null;  // To help find a place for the compute button
     
      getColors();
      Vector functions = getFunctions();
      if (!funcInput && sliders.size() == 0)  // nothing to put in the input panel
         return;
      JCMPanel panel = new JCMPanel();
      if (! "no".equalsIgnoreCase(getParameter("TwoInputColumns","no")))
         panel.setLayout(new GridLayout(0,2,12,3));
      else 
         panel.setLayout(new GridLayout(0,1,3,3));
      panel.setBackground(getColorParam("PanelBackground", Color.lightGray));
      if (funcInput) { // make an input box for each function and add it to the panel
         inputs = new ExprIn[functions.size()];
         for (int i = 0; i < functions.size(); i++) {
            Panel p = makeFunctionInput(functions,i);
            if (firstPanel == null)
               firstPanel = p;
            panel.add(p);
         }
      }
      else {  // just make graphs from the function definition strings.
         graphs = new Graph1D[functions.size()];
         for (int i = 0; i < functions.size(); i++) {
            graphs[i] = new Graph1D();
            graphs[i].setColor(graphColors[ i % graphColors.length ]);
            String def = ((String)functions.elementAt(i)).trim();
            if (def.length() > 0) {  // if the definition string is empty, leave graph"s function undefined
                Function f = new SimpleFunction( parser.parse(def), xVar );
                graphs[i].setFunction(f);
            }
         }
      }
      for (int i = 0; i < sliders.size(); i++) {  // add sliders to the input panel
         JCMPanel p = new JCMPanel();
         VariableSlider slide = (VariableSlider)sliders.elementAt(i);
         p.add(slide, BorderLayout.CENTER);
         p.add(new DisplayLabel("  " + slide.getName() + " = # ", new Value[] { slide.getVariable() } ), 
                      BorderLayout.EAST);
         panel.add(p);
         slide.setOnUserAction(mainController);
      }
      
      if (computeButton != null) {  // find a place for the compute button!
         if (functions.size() == 1)
            firstPanel.add(computeButton, BorderLayout.EAST);
         else if (limitsPanel == null) {
            Panel p = new Panel();
            p.add(computeButton);
            panel.add(p);  
         }
         // otherwise, add it at the end of setUpLimitPanel();
      }
      
      mainPanel.add(panel, BorderLayout.SOUTH);
      
   } // end setUpBottomPanel()
   protected void setUpLimitsPanel() { // add compute button if it hasn"t been put somewhere else
      super.setUpLimitsPanel();
      if (limitsPanel != null && computeButton != null && functionCt != 1)
         limitsPanel.addComponent(computeButton);
   }
   protected void setUpCanvas() { // Overridden to add the graph to the canvas.
      super.setUpCanvas();  // Do the default setup.
      // set up bottom panel has already been defined
      // add the graphs to the canvas
      
      if (graphs != null) {
         for (int i = 0; i < graphs.length; i++)
            canvas.add(graphs[i]);
      }
      else {
         for (int i = 0; i < inputs.length; i++)
            canvas.add(inputs[i].graph);
      }
   } // end setUpCanvas

   protected void doLoadExample(String example) {
         // This method is called when the user loads an example from the 
         // example menu (if there is one).  It overrides an empty method
         // in GenericGraphApplet.
         //   For the FamiliesOfGraphs applet, the example string should contain
         // an expression that defines the function to be graphed.  This must
         // be followed by a semicolon and list of zero or more numbers.
         // Then there is another semicolon and one or more function definitions,
         // separated by semicolons.  You can have as many function
         // definitions as you have functions in your applet setup.
         // (Note that having the numbers before the
         // functions is different from the format of examples in all the
         // other configurable applets.  This is to allow more than one function.)  Note that even if you leave
         // out the numbers, you still need two semicolons.  The list of numbers has the following meaning:
         // The first four numbers give the x- and y-limits to be used for the
         // example.  If they are not present, then -5,5,-5,5 is used.  The
         // remaining numbers occur in groups of three. Each group give the maximum, minimum, and value of a parameters that was defined
         // with the "Parameter", "Parameter1", ... applet params.
         
      int pos = example.indexOf(";");
      
      double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
      if (pos > 0) { 
               // Get limits from example text.
         String nums = example.substring(0,pos);
         example = example.substring(pos+1);
         StringTokenizer toks = new StringTokenizer(nums, " ,");
         if (toks.countTokens() >= 4) {
            for (int i = 0; i < 4; i++) {
               try {
                   Double d = new Double(toks.nextToken());
                   limits[i] = d.doubleValue();
               }
               catch (NumberFormatException e) {
               }
            }
         }
         int i = 0;
         while (i < sliders.size() && toks.hasMoreElements()) {
               // Look for a value for the i-th slider.
            try {
                double min = (new Double(toks.nextToken())).doubleValue();
                double max = (new Double(toks.nextToken())).doubleValue();
                double d = (new Double(toks.nextToken())).doubleValue();
                VariableSlider slider = ((VariableSlider)sliders.elementAt(i));
                slider.setMin(new Constant(min));
                slider.setMax(new Constant(max));
                slider.setVal(d);
            }
            catch (Exception e) {
            }
            i++;
         }
      }
      
      // Set up the example data and recompute everything.
      StringTokenizer toks = new StringTokenizer(example,";");
      int funcNum = 0;
      while (funcNum < functionCt) {
         if (toks.hasMoreElements()) {  // define the function using definition from example text
             String def = toks.nextToken();
             if (graphs != null) {
                try {
                    graphs[funcNum].setFunction(new SimpleFunction( parser.parse(def), xVar ));
                 }
                 catch (ParseError e) {
                    graphs[funcNum].setFunction(null); 
                 }
             }
             else
                inputs[funcNum].setText(def);
         }
         else {  // function is undefined
            if (graphs != null)
               graphs[funcNum].setFunction(null);
            else
               inputs[funcNum].setText("");
         }
         funcNum++;
      }
      CoordinateRect coords = canvas.getCoordinateRect(0);
      coords.setLimits(limits);
      coords.setRestoreBuffer();
      mainController.rupute();
      
   } // end doLoadExample()
 
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new MultiGraph();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }   
   
} // end class MultiGraph





Draw Your Own Contour Function

import java.awt.*;
import java.applet.*;
import graph.*;
/*
**************************************************************************
**
**                      Applet parse2d
**
**************************************************************************
**    Copyright (C) 1995, 1996 Leigh Brookshaw
**
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation; either version 2 of the License, or
**    (at your option) any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************
*
* This applet uses the ParseFunction class to parse an input string
* and plot the result.
*
*************************************************************************/
public class parse2d extends Applet {
      Contour graph         = new Contour();   // Graph class to do the plotting
      Axis xaxis;
      Axis yaxis;
      DataSet data;
      TextField cinput     = new TextField(4);       // Number of contours 
      TextField xinput     = new TextField(4);       // X grid dimension 
      TextField yinput     = new TextField(4);       // Y grid dimension 
      TextField xmininput  = new TextField(10);      // Minimum x value input
      TextField xmaxinput  = new TextField(10);      // Maximum x value input
      TextField ymininput  = new TextField(10);      // Minimum y value input
      TextField ymaxinput  = new TextField(10);      // Maximum y value input
      TextField finput     = new TextField(40);      // Input for the function to plot
      Button plot          = new Button("Plot It!"); // Button to plot it.


      public void init() {
         Label title            = new Label(
                                "Function Parsing & Contouring",Label.CENTER);
         Panel panel            = new Panel();
         GridBagLayout gridbag  = new GridBagLayout();
         GridBagConstraints  c  = new GridBagConstraints();
         Font font              = new Font("TimesRoman",Font.PLAIN,15);
         title.setFont(new Font("TimesRoman",Font.PLAIN,25));
          
         
         setLayout(new BorderLayout() );
         add("North",title);
         add("Center",panel);
         finput.setText("x*y*(sin(x)/x+sin(y)/y)");
         cinput.setText("20"); 
         xinput.setText("50"); 
         yinput.setText("50"); 
         xmininput.setText("-10"); 
         xmaxinput.setText("10"); 
         ymininput.setText("-10"); 
         ymaxinput.setText("10"); 
         panel.setLayout(gridbag);
   /*
   ** create labels for all the text input fields
   */
         Label clabel    = new Label("Number of Contours");         
         Label xlabel    = new Label("X grid dimension");         
         Label ylabel    = new Label("Y grid dimension");         
         Label xminlabel = new Label("Minimum x Value");
         Label xmaxlabel = new Label("Maximum x Value");
         Label yminlabel = new Label("Minimum y Value");
         Label ymaxlabel = new Label("Maximum y Value");
         Label flabel    = new Label("Function");
         /*
   ** Set the fonts and colors to use
   */
         clabel.setFont(font);
         xlabel.setFont(font);
         ylabel.setFont(font);
         flabel.setFont(font);
         xminlabel.setFont(font);
         xmaxlabel.setFont(font);
         yminlabel.setFont(font);
         ymaxlabel.setFont(font);
         
         cinput.setFont(font);
         cinput.setBackground(Color.lightGray);
         xinput.setFont(font);
         xinput.setBackground(Color.lightGray);
         yinput.setFont(font);
         yinput.setBackground(Color.lightGray);
         finput.setFont(font);
         finput.setBackground(Color.lightGray);
         xmininput.setFont(font);
         xmininput.setBackground(Color.lightGray);
         xmaxinput.setFont(font);
         xmaxinput.setBackground(Color.lightGray);
         ymininput.setFont(font);
         ymininput.setBackground(Color.lightGray);
         ymaxinput.setFont(font);
         ymaxinput.setBackground(Color.lightGray);
         plot.setFont(font);
         plot.setBackground(Color.green);

   /*
   ** First row of the GridBag contains the plot
   */
         c.weightx = 1.0;
         c.weighty = 1.0;
         c.gridwidth = 4;
         c.gridwidth=GridBagConstraints.REMAINDER;
         c.fill  =  GridBagConstraints.BOTH;
         
         gridbag.setConstraints(graph,c);
         
   /*
   ** Second row of the gridBag contains the function input and the
   ** plotit button
   */
         c.fill  =  GridBagConstraints.NONE;
         c.weightx=0.0;
         c.weighty=0.0;
         c.gridheight=1;
         
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(flabel,c);
         
         c.anchor = GridBagConstraints.CENTER;
         c.gridwidth=GridBagConstraints.RELATIVE;
         c.fill  =  GridBagConstraints.HORIZONTAL;
         gridbag.setConstraints(finput,c);
         
         c.fill = GridBagConstraints.NONE;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(plot,c);
   /*
   ** Third row contains only the Number of contours
   */
         c.gridwidth=2;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(clabel,c);
         c.anchor = GridBagConstraints.WEST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(cinput,c);
         
   /*
   ** Fourth row contains the grid dimensions
   */
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(xlabel,c);
         c.anchor = GridBagConstraints.WEST;
         gridbag.setConstraints(xinput,c);
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(ylabel,c);
         c.anchor = GridBagConstraints.WEST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(yinput,c);
   /*
   ** Fifth row contains the x range of the grid
   */
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(xminlabel,c);
         c.anchor = GridBagConstraints.WEST;
         gridbag.setConstraints(xmininput,c);
         
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(xmaxlabel,c);
         c.anchor = GridBagConstraints.WEST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(xmaxinput,c);

   /*
   ** Sixth row contains the y range of the grid
   */
         c.gridwidth=1;
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(yminlabel,c);
         c.anchor = GridBagConstraints.WEST;
         gridbag.setConstraints(ymininput,c);
         
         c.anchor = GridBagConstraints.EAST;
         gridbag.setConstraints(ymaxlabel,c);
         c.anchor = GridBagConstraints.WEST;
         c.gridwidth=GridBagConstraints.REMAINDER;
         gridbag.setConstraints(ymaxinput,c);
         
         
         panel.add(graph);
         panel.add(flabel);
         panel.add(finput);
         panel.add(plot);
         panel.add(clabel);
         panel.add(cinput);
         panel.add(xlabel);
         panel.add(xinput);
         panel.add(ylabel);
         panel.add(yinput);
         panel.add(xminlabel);
         panel.add(xmininput);
         panel.add(xmaxlabel);
         panel.add(xmaxinput);
         panel.add(yminlabel);
         panel.add(ymininput);
         panel.add(ymaxlabel);
         panel.add(ymaxinput);
         
         xaxis = graph.createXAxis();
         xaxis.setTitleText("X_axis");
         yaxis = graph.createYAxis();
         yaxis.setTitleText("Y_axis");
         graph.setDataBackground(new Color(255,200,175));
         graph.setBackground(new Color(200,150,100));
         graph.setContourColor(Color.green);
         graph.setLabelledContourColor(Color.red);
         graph.setLabelLevels(3);
         graph.setDrawLabels(false);

         graph.square = true;
         plot();
      }

      void plot() {
         int levels;
         int nx;
         int ny;
         double xmax;
         double xmin;
         double ymax;
         double ymin;
         double x, y;
         int count = 0;
         boolean error = false;
         try {
              graph.setNLevels( Integer.parseInt(cinput.getText()) );
         } catch(Exception e) {
//              this.showStatus("Error with number of contour levels!");
              System.out.println(
                             "Number of contour levels error "+e.getMessage());
              return;
         }
         try {
              nx   = Integer.parseInt(xinput.getText());
              ny   = Integer.parseInt(yinput.getText());
         } catch(Exception e) {
  //            this.showStatus("Error parsing grid dimensions!");
              System.out.println(
                             "Error parsing grid dimensions! "+e.getMessage());
              return;
         }
         try {
            xmax = Double.valueOf(xmaxinput.getText()).doubleValue();
            xmin = Double.valueOf(xmininput.getText()).doubleValue();
         } catch(Exception e) {
    //          this.showStatus("Error with X range!");
              System.out.println("X range error "+e.getMessage());
              return;
         }
         try {
            ymax = Double.valueOf(ymaxinput.getText()).doubleValue();
            ymin = Double.valueOf(ymininput.getText()).doubleValue();
         } catch(Exception e) {
      //        this.showStatus("Error with Y range!");
              System.out.println("Y range error "+e.getMessage());
              return;
         }
         if(xmin>=xmax || ymin>= ymax ) {
        //      this.showStatus("Error with Grid range!");
              System.out.println("grid range error! ");
              return;
         } 
         if( nx < 2 || ny < 2 ) {
          //    this.showStatus("Error with Grid dimensions!");
              System.out.println("grid dimension error!");
              return;
         }
             
         graph.setRange(xmin,xmax,ymin,ymax);
//         this.showStatus("Parsing Function!");
         ParseFunction function = new ParseFunction(finput.getText());
         if(!function.parse()) {
              this.showStatus("Failed to parse function!");
              System.out.println("Failed to parse function!");
              return;
         }

         double d[] = new double[nx*ny];
//         this.showStatus("Calculating Grid Values!");
         count = 0;
         for(int j=0; j<ny; j++) {
             y = ymin + j*(ymax-ymin)/(ny-1);
             for(int i=0; i<nx; i++) {
                x = xmin + i*(xmax-xmin)/(nx-1);
             try {
                   d[count++] = function.getResult(x,y);
             } catch(Exception e) {
                   d[count++] = 0.0;
                   error = true; }
       }
         }
 
         if( error ) {
  //           this.showStatus("Error while Calculating points!"); 
             System.out.println("Error while calculating points!");
   }
         graph.setGrid(d,nx,ny);
//         this.showStatus("Calculating Contours!");
         graph.repaint();
      }

     public boolean action(Event e, Object a) {
         if(e.target instanceof Button) {
             if( plot.equals(e.target) ) {
                  plot();
                  return true;
             }
         }

         return false;
       }
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new parse2d();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }

}





Function Composition

/*************************************************************************
*                                                                        *
*  This source code file, and compiled classes derived from it, can      *
*  be used and distributed without restriction, including for commercial *
*  use.  (Attribution is not required but is appreciated.)               * 
*                                                                        *
*   David J. Eck                                                         *
*   Department of Mathematics and Computer Science                       *
*   Hobart and William Smith Colleges                                    *
*   Geneva, New York 14456,   USA                                        *
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
*                                                                        *
*************************************************************************/

import java.awt.*;
import java.awt.event.*;
import java.util.StringTokenizer;
import java.applet.Applet;
import edu.hws.jcm.data.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.awt.*;
import edu.hws.jcm.functions.*;
// A Function composation applet displays the graphs of two functions, f(x) and g(x), and their
// coposition, g(f(x)).  It marks points (x,f(x)), (f(x),g(f(x)), and (x,g(f(x))) on the respective
// graphs.  The user controls the value of x by dragging a red square along the x-axis of the first
// graph.  The functions f and g can be given as table functions instead of expressions.  The
// user controls this by clicking on check boxes.  When a table function is displayed, the user
// can modify it by dragging its points.  Optionally, the apple can also display tangent lines
// to the graphs.  The slopes of the tangent line are supposed to illustrate the chain rule.
// Note:  This inherits from GenericGraphApplet, but a lot of code in that applet is superceded
// here.  In particular, there is no possibility of having a limit control panel.
public class FunctionComposition extends GenericGraphApplet implements ActionListener, ItemListener {
   Button zoomInButton, zoomOutButton, restoreButton, equalizeButton;  // Control buttons for
                                                                       // setting limits on coordinate rects.
   
   Button fComputeButton, gComputeButton;  // Buttons that the user can press when she enters a new function.
                                           // If the displayed function is a table function, the function"s values
                                           // are all reset to zero.
   Variable pointX;  // The x-coordinate that is marked on the graph of f(x)
   
   // There are two possibilities for each function -- an expression or a table.
   // I need variables for keeping track of both possibilities.  They are swapped in 
   // and out when the user clicks on a check box.  They can also be swapped when
   // an example is loaded.  The data for the functions:
   
   Checkbox fCheck, gCheck;  // checkboxes for switching between the two versions of the functions.
   
   ExpressionInput fInput, gInput;  // Input boxes for the definitions of f and g.
   
   Function fFunc, gFunc;  // The functions, defined by expressions.
   Graph1D fGraph, gGraph; // The graphs of the functions defined by expressions
   
   TableFunction fTable, gTable;  // The functions, defined by tables.
   TableFunctionGraph fTableGraph, gTableGraph;  // The graphs of the functions defined by tables.
   
   boolean fTableShown, gTableShown;  // keep track of which version of the function is shown.
   String fSaveText, gSaveText;  // Save the text in the input box while a table shown is shown.
   WrapperFunction fWrapper, gWrapper;  // These functions refer to f and g, whichever versions of
                                        // f and g are currently in effect.  They are used to form
                                        // the composition function, g(f(x)).  So the composed function
                                        // is valid however f and g are represented.
   
   public void setUpMainPanel() {  // Set up the applet.
   
      // basic setup, with three coordinate rects in the canvas
   
      mainController = new Controller();      
      defaultFrameSize = new int[] { 606, 306 };
      Color textColor = getColorParam("TextColor", Color.black);
      Color canvasBackground = getColorParam("CanvasColor", Color.white);
      boolean useInputs = ! "no".equalsIgnoreCase(getParameter("UseFunctionInput", "yes"));
      double[] gap = getNumericParam("Insets");
      if (gap == null || gap.length == 0 || gap[0] < 0 || gap[0] > 50)
         mainPanel.setInsetGap(3);
      else
         mainPanel.setInsetGap( (int)Math.round(gap[0]) );
      parser = new Parser(null,0);
      setUpParser();
      setUpExampleMenu(); 
      setUpTopPanel();
      
      Color color;
      color = getColorParam("BackgroundColor", Color.gray);
      mainPanel.setBackground(color);
      color = getColorParam("ForegroundColor", Color.black);
      mainPanel.setForeground(color);
      double[] limits = getNumericParam("Limits");
      if (limits == null || limits.length < 4)
         limits = new double[] { -5, 5, -5 ,5 };
   
      canvas = new DisplayCanvas();
      mainPanel.add(canvas,BorderLayout.CENTER);  // add canvas to panel
      
      canvas.setBackground(canvasBackground);
      if ( ! "no".equalsIgnoreCase(getParameter("UseMouseZoom", "no")) )
         canvas.setHandleMouseZooms(true);
      if ( ! "no".equalsIgnoreCase(getParameter("UseOffscreenCanvas", "yes")) )
         canvas.setUseOffscreenCanvas(true);
      canvas.addCoordinateRect(new CoordinateRect(limits[0],limits[1],limits[2],limits[3]), 0, 1.0/3.0, 0, 1,null);
      canvas.addCoordinateRect(new CoordinateRect(limits[0],limits[1],limits[2],limits[3]),1.0/3.0, 2.0/3.0, 0,1,null);
      canvas.addCoordinateRect(new CoordinateRect(limits[0],limits[1],limits[2],limits[3]),2.0/3.0, 1, 0, 1, null);
      
      if ( ! "no".equalsIgnoreCase(getParameter("UseGrid", "no")) ) {
         color = getColorParam("GridColor");
         Grid g = new Grid();
         if (color != null)
            g.setColor(color);
         canvas.add(g,0);
         g = new Grid();
         if (color != null)
            g.setColor(color);
         canvas.add(g,1);
         g = new Grid();
         if (color != null)
            g.setColor(color);
         canvas.add(g,2);
      }
      
      canvas.add(makeAxes(), 0);
      canvas.add(makeAxes(), 1);
      canvas.add(makeAxes(), 2);
      
      // Make the expression functions
      
      fSaveText = getParameter("Function"," 3 - " + xVar.getName() + "^2/2"); 
      gSaveText = getParameter("SecondFunction", " sin(" + xVar.getName() + ")"); 
      
      if (useInputs) {
         fInput = new ExpressionInput(fSaveText, parser);
         gInput = new ExpressionInput(gSaveText, parser);
         fFunc = fInput.getFunction(xVar);
         gFunc = gInput.getFunction(xVar);
      }
      else {
         fFunc = new SimpleFunction( parser.parse(fSaveText), xVar );
         gFunc = new SimpleFunction( parser.parse(gSaveText), xVar );
      }
      
      fGraph = new Graph1D(fFunc);
      gGraph = new Graph1D(gFunc);
      
      // Create the wrapper functions for f and g and use it to make a compostion function
      
      fWrapper = new WrapperFunction(fFunc);
      fWrapper.setName("f");
      gWrapper = new WrapperFunction(gFunc);
      gWrapper.setName("g");
      Parser p1 = new Parser();  // parser for making the composition function
      p1.add(fWrapper);
      p1.add(gWrapper);
      ExpressionFunction comp = new ExpressionFunction("h", new String[] { "x" }, "g(f(" + xVar.getName() + "))", p1);
      Graph1D compositionGraph = new Graph1D(comp);
      
      fTableShown = gTableShown = false;
            
      // Make table functions.  If a table function is specified in applet params, but no 
      // expression is specified, show the table function.
      String tf = getParameter("TableFunction");
      if (tf != null) {
         try {
            fTable = parseTableFuncDef(tf);
         }
         catch (Exception e) {
            tf = null;
         }
      }
      if (tf == null) {
         fTable = new TableFunction();
         fTable.addIntervals(6, -5, 5);
      }
      fTableGraph = new TableFunctionGraph(fTable);
      fTableGraph.setInteractive(true);
      if (getParameter("Function") == null && tf != null) {  // show table function at startup
         fGraph.setVisible(false);
         fTableShown = true;
         fWrapper.setFunction(fTable);
         if (fInput != null) {
            fInput.setEnabled(false);
            fInput.setThrowErrors(false);
            fInput.setText("Drag points to modify function.");
         }
      }
      else {
         fTableGraph.setVisible(false);
      }
      
      tf = getParameter("SecondTableFunction");
      if (tf != null) {
         try {
            gTable = parseTableFuncDef(tf);
         }
         catch (Exception e) {
            tf = null;
         }
      }
      if (tf == null) {
         gTable = new TableFunction();
         gTable.addIntervals(6, -5, 5);
      }
      gTableGraph = new TableFunctionGraph(gTable);
      gTableGraph.setInteractive(true);
      if (getParameter("SecondFunction") == null && tf != null) {  // show table function at startup
         gGraph.setVisible(false);
         gTableShown = true;
         gWrapper.setFunction(gTable);
         if (gInput != null) {
            gInput.setEnabled(false);
            gInput.setThrowErrors(false);
            gInput.setText("Drag points to modify function.");
         }
      }
      else {
         gTableGraph.setVisible(false);
      }
      
      // Create the stuff for marking points on each graph
      
      DraggablePoint point = new DraggablePoint(DraggablePoint.SQUARE);  // gives x-coord
      Color pointColor1 = getColorParam("PointColor1", Color.red);
      Color pointColor2 = getColorParam("PointColor2", new Color(0,200,0));
      Color pointColor3 = getColorParam("PointColor3", new Color(100,100,255));
      point.setColor(pointColor1);
      point.clampY(0);
      point.setLocation(1,0);
      canvas.add(point,0);
      pointX = point.getXVar();
      Value fOfX = new ValueMath(fWrapper, pointX);
      Value gOfFOfX = new ValueMath(gWrapper, fOfX);
     
      DrawGeometric line1;
      line1 = new DrawGeometric( DrawGeometric.LINE_ABSOLUTE, pointX, new Constant(0), pointX, fOfX );
      line1.setColor(pointColor1);
      canvas.add(line1, 0);
      
      DrawGeometric line2;
      line2 = new DrawGeometric( DrawGeometric.LINE_ABSOLUTE, pointX, fOfX, new Constant(0), fOfX );
      line2.setColor(pointColor2);
      canvas.add(line2, 0);
      
      DrawGeometric line3;
      line3 = new DrawGeometric( DrawGeometric.LINE_ABSOLUTE, fOfX, new Constant(0), fOfX, gOfFOfX );
      line3.setColor(pointColor2);
      canvas.add(line3, 1);
      
      DrawGeometric line4;
      line4 = new DrawGeometric( DrawGeometric.LINE_ABSOLUTE, fOfX, gOfFOfX, new Constant(0), gOfFOfX );
      line4.setColor(pointColor3);
      canvas.add(line4, 1);
      
      DrawGeometric line5;
      line5 = new DrawGeometric( DrawGeometric.LINE_ABSOLUTE, pointX, new Constant(0), pointX, gOfFOfX );
      line5.setColor(pointColor1);
      canvas.add(line5, 2);
      
      DrawGeometric line6;
      line6 = new DrawGeometric( DrawGeometric.LINE_ABSOLUTE, pointX, gOfFOfX, new Constant(0), gOfFOfX );
      line6.setColor(pointColor3);
      canvas.add(line6, 2);
      
      line1.setLineWidth(2);
      line2.setLineWidth(2);
      line3.setLineWidth(2);
      line4.setLineWidth(2);
      line5.setLineWidth(2);
      line6.setLineWidth(2);
      
      // Add the graphs
      
      Color gc = getColorParam("GraphColor", Color.magenta);
      fGraph.setColor(gc);
      gGraph.setColor(gc);
      fTableGraph.setColor(gc);
      gTableGraph.setColor(gc);
      compositionGraph.setColor(gc);
      canvas.add(fGraph, 0);
      canvas.add(fTableGraph, 0);
      canvas.add(gGraph, 1);
      canvas.add(gTableGraph, 1);
      canvas.add(compositionGraph, 2);
      
      // Create tangent lines, if they are called for by an applet param
      
      TangentLine tangent1=null, tangent2=null, tangent3=null;
      DrawString ts1=null, ts2=null, ts3=null;
      if (! "no".equalsIgnoreCase(getParameter("ShowTangents","no"))) {
         Color tangentColor = getColorParam("TangentColor", Color.gray);
         tangent1 = new TangentLine(pointX,fWrapper);
         tangent1.setColor(tangentColor);
         canvas.add(tangent1,0);
         tangent2 = new TangentLine(fOfX,gWrapper);
         tangent2.setColor(tangentColor);
         canvas.add(tangent2,1);
         tangent3 = new TangentLine(pointX,comp);
         tangent3.setColor(tangentColor);
         canvas.add(tangent3,2);
         if ("yes".equalsIgnoreCase(getParameter("ShowSlopes","yes"))) {
            ts1 = new DrawString("slope = #", DrawString.TOP_RIGHT, 
                            new Value[] { new ValueMath(fWrapper.derivative(1), pointX) });
            ts1.setColor(textColor);
            ts1.setNumSize(6);
            canvas.add(ts1,0);
            ts2 = new DrawString("slope = #", DrawString.TOP_RIGHT, 
                            new Value[] { new ValueMath(gWrapper.derivative(1), fOfX) });
            ts2.setColor(textColor);
            ts2.setNumSize(6);
            canvas.add(ts2,1);
            ts3 = new DrawString("slope = #", DrawString.TOP_RIGHT, 
                            new Value[] { new ValueMath(comp.derivative(1), pointX) });
            ts3.setColor(textColor);
            ts3.setNumSize(6);
            canvas.add(ts3,2);
         }
      }
      
      // Create DrawStrings for displaying information over the graphs.
      
      if ("yes".equalsIgnoreCase(getParameter("ShowFunctionNames","yes"))) {
         DrawString d = new DrawString("y=f(" + xVar.getName() + ")");
         d.setColor(textColor);
         canvas.add(d, 0);
         d = new DrawString("y=g(" + xVar.getName() + ")");
         d.setColor(textColor);
         canvas.add(d, 1);
         d = new DrawString("y=g(f(" + xVar.getName() + "))");
         d.setColor(textColor);
         canvas.add(d, 2);
      }
      
      DrawString ds1=null, ds2=null, ds3=null;
      if ("yes".equalsIgnoreCase(getParameter("ShowCoordinates","yes"))) {
         ds1 = new DrawString("f(#) = #", DrawString.BOTTOM_CENTER, new Value[] { pointX, fOfX });
         ds1.setNumSize(6);
         ds1.setColor(textColor);
         ds1.setBackgroundColor(canvasBackground);
         canvas.add(ds1, 0);
         ds2 = new DrawString("g(#) = #", DrawString.BOTTOM_CENTER, new Value[] { fOfX, gOfFOfX });
         ds2.setNumSize(6);
         ds2.setColor(textColor);
         ds2.setBackgroundColor(canvasBackground);
         canvas.add(ds2, 1);
         ds3 = new DrawString("g(f(#)) = #", DrawString.BOTTOM_CENTER, new Value[] { pointX, gOfFOfX });
         ds3.setNumSize(6);
         ds3.setColor(textColor);
         ds3.setBackgroundColor(canvasBackground);
         canvas.add(ds3, 2);
      }
      
      // Add panner and borders
      
      if (! "no".equalsIgnoreCase(getParameter("UsePanner", "no")) ) {
         canvas.add(new Panner(), 0);
         canvas.add(new Panner(), 1);
         canvas.add(new Panner(), 2);
      }
      
      int borderWidth;
      double[] bw = getNumericParam("BorderWidth");
      if (bw == null || bw.length == 0 || bw[0] > 25)
         borderWidth = 1;
      else
         borderWidth = (int)Math.round(bw[0]);
      if (borderWidth > 0) {
         Color bc = getColorParam("BorderColor", Color.black);
         canvas.add(new DrawBorder(bc, borderWidth), 0);
         canvas.add(new DrawBorder(bc, borderWidth), 1);
         canvas.add(new DrawBorder(bc, borderWidth), 2);
      }
      
      // Set up the bottom panel to hold inputs and control buttons, unless an
      // applet param has specified that no input panel is desired.
      if ( useInputs ) {
          Panel bottom = new Panel();
          bottom.setLayout(new BorderLayout(3,3));
          bottom.setBackground(getColorParam("PanelBackground", Color.lightGray));
          mainPanel.add(bottom,BorderLayout.SOUTH);
          
          Panel left = new Panel();
          left.setLayout(new GridLayout(0,1));
          bottom.add(left, BorderLayout.CENTER);
          Panel right = new Panel();
          right.setLayout(new GridLayout(0,2));
          bottom.add(right, BorderLayout.EAST);
          
          Panel fPanel = new Panel();
          fPanel.setLayout(new BorderLayout());
          fPanel.add(new Label(" f(" + xVar.getName() + ") = "), BorderLayout.WEST);
          fPanel.add(fInput, BorderLayout.CENTER);
          Panel fp = new Panel();
          fp.setLayout(new GridLayout(1,2));
          fCheck = new Checkbox("Use Mouse");
          if (fTableShown)
             fCheck.setState(true);
          fCheck.addItemListener(this);
          fp.add(fCheck);
          fComputeButton = new Button("New f(" + xVar.getName() + ")");
          fComputeButton.addActionListener(this);
          fp.add(fComputeButton);
          fPanel.add(fp,BorderLayout.EAST);
          left.add(fPanel);
          Panel gPanel = new Panel();
          gPanel.setLayout(new BorderLayout());
          gPanel.add(new Label(" g(" + xVar.getName() + ") = "), BorderLayout.WEST);
          gPanel.add(gInput, BorderLayout.CENTER);
          Panel gp = new Panel();
          gp.setLayout(new GridLayout(1,2));
          gCheck = new Checkbox("Use Mouse");
          if (gTableShown)
             gCheck.setState(true);
          gCheck.addItemListener(this);
          gp.add(gCheck);
          gComputeButton = new Button("New g(" + xVar.getName() + ")");
          gComputeButton.addActionListener(this);
          gp.add(gComputeButton);
          gPanel.add(gp,BorderLayout.EAST);
          left.add(gPanel);
          
          zoomInButton = new Button("Zoom In");
          right.add(zoomInButton);
          zoomInButton.addActionListener(this);
          zoomOutButton = new Button("Zoom Out");
          right.add(zoomOutButton);
          zoomOutButton.addActionListener(this);
          equalizeButton = new Button("EqualizeAxes");
          equalizeButton.addActionListener(this);
          right.add(equalizeButton);
          restoreButton = new Button("Restore Limits");
          right.add(restoreButton);
          restoreButton.addActionListener(this);
          fInput.setOnUserAction(mainController);
          gInput.setOnUserAction(mainController);
          mainController.add(fInput);
          mainController.add(gInput);
      }
      
      // finish setting up controllers
      
      fTableGraph.setOnDrag(mainController);
      gTableGraph.setOnDrag(mainController);
      mainController.add(canvas);
      mainController.setErrorReporter(canvas);
      
      Controller lineController = new Controller();  // doesn"t recompute the graphs
      mainController.add(lineController);
      point.setOnUserAction(lineController);
      lineController.add(point);
      lineController.add(line1);
      lineController.add(line2);
      lineController.add(line3);
      lineController.add(line4);
      lineController.add(line5);
      lineController.add(line6);
      if (ds1 != null) {
         lineController.add(ds1);
         lineController.add(ds2);
         lineController.add(ds3);
      }
      if (tangent1 != null) {
         lineController.add(tangent1);
         lineController.add(tangent2);
         lineController.add(tangent3);
      }
      if (ts1 != null) {
         lineController.add(ts1);
         lineController.add(ts2);
         lineController.add(ts3);
      }
      
   } // end makeMainPanel()
   
   

   public void itemStateChanged(ItemEvent evt) {
         // Respond when user clicks one of the check boxes.
      Object src = evt.getSource();
      if (src == fCheck) {  // Swap the f table function in or out
         boolean check = fCheck.getState();
         if (check == fTableShown)
            return;
         fTableShown = check;
         fGraph.setVisible(!fTableShown);
         fTableGraph.setVisible(fTableShown);
         if (fTableShown) {
            fWrapper.setFunction(fTable);
            fSaveText = fInput.getText();
            fInput.setText("Drag points to modify function.");
            fInput.setThrowErrors(false);
            fInput.setEnabled(false);
         }
         else {
            fWrapper.setFunction(fFunc);
            fInput.setText(fSaveText);
            fInput.setThrowErrors(true);
            fInput.setEnabled(true);
         }
         mainController.rupute();
      }
      else if (src == gCheck) { // Swap the g table function in or out
         boolean check = gCheck.getState();
         if (check == gTableShown)
            return;
         gTableShown = check;
         gGraph.setVisible(!gTableShown);
         gTableGraph.setVisible(gTableShown);
         if (gTableShown) {
            gWrapper.setFunction(gTable);
            gSaveText = gInput.getText();
            gInput.setText("Drag points to modify function.");
            gInput.setThrowErrors(false);
            gInput.setEnabled(false);
         }
         else {
            gWrapper.setFunction(gFunc);
            gInput.setText(gSaveText);
            gInput.setThrowErrors(true);
            gInput.setEnabled(true);
         }
         mainController.rupute();
      }
   } // end itemStateChanged()
   
   public void actionPerformed(ActionEvent evt) {
        // respond when the user clicks one of the control buttons.
      Object src = evt.getSource();
      if (src == zoomInButton) {
         canvas.getCoordinateRect(0).zoomIn();
         canvas.getCoordinateRect(1).zoomIn();
         canvas.getCoordinateRect(2).zoomIn();
      }
      else if (src == zoomOutButton) {
         canvas.getCoordinateRect(0).zoomOut();
         canvas.getCoordinateRect(1).zoomOut();
         canvas.getCoordinateRect(2).zoomOut();
      }
      else if (src == restoreButton) {
         canvas.getCoordinateRect(0).restore();
         canvas.getCoordinateRect(1).restore();
         canvas.getCoordinateRect(2).restore();
      }
      else if (src == equalizeButton) {
         canvas.getCoordinateRect(0).equalizeAxes();
         canvas.getCoordinateRect(1).equalizeAxes();
         canvas.getCoordinateRect(2).equalizeAxes();
      }
      else if (src == fComputeButton) {
         if (fTableShown) {
            int ct = fTable.getPointCount();
            double val;
            if (0 < canvas.getCoordinateRect(0).getYmin() || 0 > canvas.getCoordinateRect(0).getYmax())
               val = canvas.getCoordinateRect(0).getYmin();
            else 
               val = 0;
            for (int i = 0; i < ct; i++)
               fTable.setY(i,val);
         }
         mainController.rupute();
      }
      else if (src == gComputeButton) {
         if (gTableShown) {
            int ct = gTable.getPointCount();
            double val;
            if (0 < canvas.getCoordinateRect(1).getYmin() || 0 > canvas.getCoordinateRect(1).getYmax())
               val = canvas.getCoordinateRect(1).getYmin();
            else
               val = 0;
            for (int i = 0; i < ct; i++)
               gTable.setY(i,val);
         }
         mainController.rupute();
      }
      else {
         super.actionPerformed(evt);
      }
   } // end actionPerformed()
   
   
   protected void doLoadExample(String example) {
         // This method is called when the user loads an example from the 
         // example menu (if there is one).  It overrides an empty method
         // in GenericGraphApplet.
         //   The example string should contain two function definitions,
         // separated by a semicolon.  A function definition can be either
         // an expression or a table function.  These espressions can be
         // followed by a semicolon and four or five numberd.
         // The first four numbers give the x- and y-limits to be used for the
         // example.  If they are not present, then -5,5,-5,5 is used.  The
         // next number is used as the x-coordinated that is selected on
         // the graph of the first function.
         
      int pos = example.indexOf(";");
      if (pos == -1) {
         System.out.println("Illegal example -- must have two functions");
         return;
      }
      String example2 = example.substring(pos+1);
      example = example.substring(0,pos).trim();
      pos = example2.indexOf(";");   
         
      double[] limits = { -5,5,-5,5 }; // x- and y-limits to use
      if (pos > 0) { 
               // Get limits from example2 text.
         String nums = example2.substring(pos+1);
         example2 = example2.substring(0,pos).trim();
         StringTokenizer toks = new StringTokenizer(nums, " ,");
         if (toks.countTokens() >= 4) {
            for (int i = 0; i < 4; i++) {
               try {
                   Double d = new Double(toks.nextToken());
                   limits[i] = d.doubleValue();
               }
               catch (NumberFormatException e) {
               }
            }
         }
         if (toks.hasMoreTokens()) {
                 // get the x coordinate 
            try {
               double d = (new Double(toks.nextToken())).doubleValue();
               pointX.setVal(d);
            }
            catch (NumberFormatException e) {
            }
         }
      }
      
      // Set up the example data and recompute everything.
      
      if (example.startsWith("table")) {  // install table for f(x) from example
         try {
            TableFunction tf = parseTableFuncDef(example);
            fTable = tf;
            fTableGraph.setFunction(tf);
            fWrapper.setFunction(tf);
            if (!fTableShown) {  // show table function
               if (fCheck != null)
                  fCheck.setState(true);
               fGraph.setVisible(false);
               fTableGraph.setVisible(true);
               fTableShown = true;
               if (fInput != null) {
                  fSaveText = fInput.getText();
                  fInput.setText("Drag points to modify function.");
                  fInput.setThrowErrors(false);
                  fInput.setEnabled(false);
               }
            }
         }
         catch (ParseError e) {
            System.out.println("Illegal table function for f(x) in example.");
         }
      }
      else {   // install expression function for f(x)
         try {
            if (fInput != null)
               fInput.setText(example);
            else {
               Function f = new SimpleFunction( parser.parse(example), xVar );
               fFunc = f;
               fGraph.setFunction(f);
               fWrapper.setFunction(f);
            }
            if (fTableShown) {  // show expression function
               if (fCheck != null)
                  fCheck.setState(false);
               fGraph.setVisible(true);
               fTableGraph.setVisible(false);
               fTableShown = false;
               if (fInput != null) {
                  fInput.setThrowErrors(true);
                  fInput.setEnabled(true);
               }
            }
         }
         catch (ParseError e) {
            System.out.println("Parse error for f(x) in example.");
         }
      }
      if (example2.startsWith("table")) {  // install table for fg(x) from example
         try {
            TableFunction tg = parseTableFuncDef(example2);
            gTable = tg;
            gTableGraph.setFunction(tg);
            gWrapper.setFunction(tg);
            if (!gTableShown) {  // show table function
               if (gCheck != null)
                  gCheck.setState(true);
               gGraph.setVisible(false);
               gTableGraph.setVisible(true);
               gTableShown = true;
               if (gInput != null) {
                  gSaveText = gInput.getText();
                  gInput.setText("Drag points to modify function.");
                  gInput.setThrowErrors(false);
                  gInput.setEnabled(false);
               }
            }
         }
         catch (ParseError e) {
            System.out.println("Illegal table function for g(x) in example.");
         }
      }
      else {   // install expression function for g(x)
         try {
            if (gInput != null)
               gInput.setText(example2);
            else {
               Function g = new SimpleFunction( parser.parse(example2), xVar );
               gFunc = g;
               gGraph.setFunction(g);
               gWrapper.setFunction(g);
            }
            if (gTableShown) {  // show expression function
               if (gCheck != null)
                  gCheck.setState(false);
               gGraph.setVisible(true);
               gTableGraph.setVisible(false);
               gTableShown = false;
               if (gInput != null) {
                  gInput.setThrowErrors(true);
                  gInput.setEnabled(true);
               }
            }
         }
         catch (ParseError e) {
            System.out.println("Parse error for g(x) in example.");
         }
      }
      CoordinateRect coords = canvas.getCoordinateRect(0);
      coords.setLimits(limits);
      coords.setRestoreBuffer();
      coords = canvas.getCoordinateRect(1);
      coords.setLimits(limits);
      coords.setRestoreBuffer();      
      coords = canvas.getCoordinateRect(2);
      coords.setLimits(limits);
      coords.setRestoreBuffer();      
      mainController.rupute();
      
   } // end doLoadExample()
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new FunctionComposition();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }   

} // end class FunctionComposition





Math function and bar

/*************************************************************************
*                                                                        *
*  This source code file, and compiled classes derived from it, can      *
*  be used and distributed without restriction, including for commercial *
*  use.  (Attribution is not required but is appreciated.)               * 
*                                                                        *
*   David J. Eck                                                         *
*   Department of Mathematics and Computer Science                       *
*   Hobart and William Smith Colleges                                    *
*   Geneva, New York 14456,   USA                                        *
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
*                                                                        *
*************************************************************************/

// The SimpleGraph applet is a configurable applet that displays the graph of
// a single function of one variable and computes a Riemann sum for that
// function.
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.util.StringTokenizer;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.functions.*;
import edu.hws.jcm.awt.*;

public class RiemannSums extends GenericGraphApplet {
   // Declare some private variables that are created in one method in
   // this class and used in a second method.
   private Variable intervals;       // Gives the number of intervals.
   private VariableInput intCtInput; // For letting the user enter the number of intervals.
   private Choice methodChoice;      // Gives the method to be used:  Left Endpoint, ..., Trapezoid.
   private Function func;   // The function that is graphed.
   private Graph1D graph;   // The graph of the function.
   
   private RiemannSumRects sums;
   public void itemStateChanged(ItemEvent evt) {
         // React when user changes the summation method.
       if (evt.getSource() == methodChoice) {
          sums.setMethod(methodChoice.getSelectedIndex());
          mainController.rupute();
       }
       else
          super.itemStateChanged(evt);
   }
   
   protected void setUpParameterDefaults() { // Override to give a different default function
      parameterDefaults = new java.util.Hashtable();
      String func = " 3 / (1 + " + getParameter("Variable","x") + "^2)";
      parameterDefaults.put("Function",func);
      parameterDefaults.put("ComputeButtonName","Compute!");
   }
   protected void setUpCanvas() {  // Override this to add more stuff to the canvas.
   
      // When setUpCanvas is called, the functionInput already exists, if one is
      // to be used, since it is created in setUpBopttomPanel(), which is called
      // before setUpCanvas.  If functionInput exists, add a graph of the function
      // from functionInput to the canvas.  If not, create a graph of the function
      // specified by the parameter named "Function".
      
      if (functionInput != null)
         func = functionInput.getFunction(xVar);
      else {
         String def = getParameter("Function", " abs(" + xVar.getName() + ") ^ " + xVar.getName());
         Function f = new SimpleFunction( parser.parse(def), xVar );
         func = new WrapperFunction(f);
      }
      graph = new Graph1D(func);
      Color color = getColorParam("GraphColor");
      if (color != null)
         graph.setColor(color);
         
      // Get the data for the RiemannSumRects object.  Create it (along with other
      // associated objects) and add it to the canvas.
         
      double[] intCtD = getNumericParam("IntervalCount");
      if (intCtD == null || intCtD.length < 1)
         intCtD = new double[] { 5 };
      else if (Double.isNaN(intCtD[0]) || intCtD[0] < 1 || intCtD[0] > 5000)
         intCtD[0] = 5;
      int intCt = (int)(intCtD[0]+0.5);
      
      if ("yes".equalsIgnoreCase( getParameter("UseIntervalInput", "yes") )){
         intCtInput = new VariableInput(null, "" + intCt);
         intCtInput.setInputStyle(VariableInput.INTEGER);
         intCtInput.setMin(1);
         intCtInput.setMax(5000);
         intervals = intCtInput.getVariable();
      }
      else
         intervals = new Variable(null,intCt);
      
      int method = RiemannSumRects.LEFTENDPOINT;
      String methodStr = getParameter("Method");
      if (methodStr != null && methodStr.trim().length() > 0) {
         switch (methodStr.trim().charAt(0)) {
            case "L": case "l": method = RiemannSumRects.LEFTENDPOINT; break;
            case "R": case "r": method = RiemannSumRects.RIGHTENDPOINT; break;
            case "M": case "m": method = RiemannSumRects.MIDPOINT; break;
            case "C": case "c": method = RiemannSumRects.CIRCUMSCRIBED; break;
            case "I": case "i": method = RiemannSumRects.INSCRIBED; break;
            case "T": case "t": method = RiemannSumRects.TRAPEZOID; break;
         }
      }
      
      if ("yes".equalsIgnoreCase( getParameter("UseMethodInput", "yes") )) {
         methodChoice = new Choice();
         methodChoice.add("Left Endpoint");
         methodChoice.add("Right Endpoint");
         methodChoice.add("Midpoint");
         methodChoice.add("~Circumscribed");
         methodChoice.add("~Inscribed");
         methodChoice.add("Trapezoid");
         methodChoice.select(method);
         methodChoice.addItemListener(this);
      }
      
      sums = new RiemannSumRects(func,intervals);
      sums.setMethod(method);
      canvas.add(sums);
      
      Color c = getColorParam("RectColor");
      if (c != null)
         sums.setColor(c);
      c = getColorParam("OutlineColor");
      if (c != null)
         sums.setOutlineColor(c);
         
      super.setUpCanvas();  // Do the common setup: Add the axes, for example.
      canvas.getCoordinateRect().setGap(10);  // Extra space around edges.
      canvas.add(graph);  // Add the graph to the canvas.
      
      // Add a DrawString to the canvas to show the value of the sum.
      DrawString ds = new DrawString("sum = #", DrawString.TOP_LEFT,
                           new Value[] { sums.getValueObject(RiemannSumRects.CURRENT_METHOD) } );
      ds.setBackgroundColor(getColorParam("TextBackground",Color.white));
      ds.setColor(getColorParam("TextColor",Color.black));
      ds.setFrameWidth(1);
      canvas.add(ds);
      
      mainController.add(ds);
      mainController.add(sums);
      if (intCtInput != null)
         intCtInput.setOnUserAction(mainController);
      canvas.getCoordinateRect().setOnChange(mainController);
   } // end setUpCanvas()
   
   
   protected void setUpMainPanel() {
         // Override this method to add the methodChoice menu and interval count inputs, if any,
         // to the panel.  (They were created in the setUpCanvas method.)
   
      super.setUpMainPanel(); // Do the common setup
      
      if (methodChoice == null && intCtInput == null)
         return;
         
         JCMPanel panel = new JCMPanel();
         panel.setLayout(new FlowLayout());
         panel.setBackground(getColorParam("PanelBackground",Color.lightGray));
         if (intCtInput != null) {
            panel.add(new Label("Intervals:"));
            panel.add(intCtInput);
         }
         if (methodChoice != null) {
            panel.add(new Label("Method:"));
            panel.add(methodChoice);
         }      
         if (inputPanel == null)
            mainPanel.add(panel, BorderLayout.SOUTH);
         else {
            inputPanel.setBackground(getColorParam("PanelBackground",Color.lightGray));
            inputPanel.add(panel, BorderLayout.SOUTH);
         }
      
   } // end setUpMainPanel()
   

   protected void doLoadExample(String example) {
         // This method is called when the user loads an example from the 
         // example menu (if there is one).  It overrides an empty method
         // in GenericGraphApplet.
         //   For this applet, the example string should contain
         // an expression that defines the function to be graphed.
         // This can optionally  be followed by a semicoloon and a list of four or five
         // numbers.  The first four numbers give the x- and y- limes to be used for the
         // example.  The fifth number, if present, gives the interval count.
         // After the numbers, there can be another semicolon
         // and the name of the summation method to be used.
      int pos = example.indexOf(";");
      double[] limits = { -5,5,-5,5 };  // x- and y-limits to use
      
      if (pos > 0) { // get limits, method from example text
         String limitsText = example.substring(pos+1);
         example = example.substring(0,pos);
         pos = limitsText.indexOf(";");
         if (pos > 0) {  // data includes a method name.
            String methodStr = limitsText.substring(pos+1).trim();
            limitsText = limitsText.substring(0,pos);
            if (methodStr.length() > 0) {
                int method;
                switch (methodStr.charAt(0)) {
                   case "L": case "l": method = RiemannSumRects.LEFTENDPOINT; break;
                   case "R": case "r": method = RiemannSumRects.RIGHTENDPOINT; break;
                   case "M": case "m": method = RiemannSumRects.MIDPOINT; break;
                   case "C": case "c": method = RiemannSumRects.CIRCUMSCRIBED; break;
                   case "I": case "i": method = RiemannSumRects.INSCRIBED; break;
                   case "T": case "t": method = RiemannSumRects.TRAPEZOID; break;
                   default: method = -1;
               }
               if (method >= 0) {
                  sums.setMethod(method);
                  if (methodChoice != null)  
                     methodChoice.select(method);
               }
            }
         }
         StringTokenizer toks = new StringTokenizer(limitsText, " ,");
         if (toks.countTokens() >= 4) {
            for (int i = 0; i < 4; i++) {
               try {
                   Double d = new Double(toks.nextToken());
                   limits[i] = d.doubleValue();
               }
               catch (NumberFormatException e) {
               }
            }
            if (toks.countTokens() > 0) {
                  // get number of intervals
               try {
                   Double d = new Double(toks.nextToken());
                   double intCtD = d.doubleValue();
                   if (intCtD < 1)
                      intCtD = 1;
                   else if (intCtD > 5000)
                      intCtD = 5000;
                   intervals.setVal((int)(intCtD + 0.5));
               }
               catch (NumberFormatException e) {
               }
            }
         }
      }
      
      // Set up the example data and recompute everything.
      if (functionInput != null) {
            // If there is a function input box, put the example text in it.
         functionInput.setText(example);
      }
      else { 
           // If there is no user input, set the function in the graph directly.
           // Also, in this case, func is a "WrapperFunction".  Set the
           // definition of that WrapperFunction to be the same as f
         try {
            Function f = new SimpleFunction( parser.parse(example), xVar );
            ((WrapperFunction)func).setFunction(f);
         }
         catch (ParseError e) {  
             // There should"t be parse error"s in the Web-page
             // author"s examples!  If there are, the function
             // just won"t change.
         }
      }
      CoordinateRect coords = canvas.getCoordinateRect(0);
      coords.setLimits(limits);
      coords.setRestoreBuffer();
      mainController.rupute();
      
   } // end doLoadExample()
   
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new RiemannSums();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }   
} // end class RiemannSums





Math Function Chart

import java.awt.*;
import java.applet.*;
import java.net.URL;
import graph.*;
/*************************************************************************
**
**    Applet example1a
**                                              Version 1.0   January 1996
**
**************************************************************************
**    Copyright (C) 1996 Leigh Brookshaw
**
**    This program is free software; you can redistribute it and/or modify
**    it under the terms of the GNU General Public License as published by
**    the Free Software Foundation; either version 2 of the License, or
**    (at your option) any later version.
**
**    This program is distributed in the hope that it will be useful,
**    but WITHOUT ANY WARRANTY; without even the implied warranty of
**    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
**    GNU General Public License for more details.
**
**    You should have received a copy of the GNU General Public License
**    along with this program; if not, write to the Free Software
**    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**************************************************************************
**
**    This is a simple applet that demonstrates how to use the basic features
**    of the Plotting Class library. The data is calculated locally by
**    the applet
**
*************************************************************************/
public class example1a extends Applet {
      Graph2D graph1;
      Graph2D graph2;
      DataSet data1;
      DataSet data2;
      Axis    xaxis1;
      Axis    xaxis2;
      Axis    yaxis1;
      Axis    yaxis2;
      double data[];
      int np = 25;
      URL markersURL;
      Markers markers;
      Panel      panel;
      Label title;
      public void init() {
        int i;
        int j;
        double data[] = new double[2*np];
/*
**      Get the passed parameters
*/
        String st = "TITLE";
        String mfile    = "marker.txt";
/*
**      Create the Graph instance and modify the default behaviour
*/
        graph1 = new Graph2D();
        graph1.drawzero = false;
        graph1.drawgrid = false;
        graph1.borderRight = 0;
        graph1.setDataBackground(new Color(255,230,200));

        graph2 = new Graph2D();
        graph2.drawzero = false;
        graph2.drawgrid = false;
        graph2.borderLeft =  0;
        graph2.setDataBackground(new Color(230,230,230));
/*
**      Build the title
*/
        title = new Label(st, Label.CENTER);
        title.setFont(new Font("TimesRoman",Font.PLAIN,20));

/*
**      Load a file containing Marker definitions
*/
        try {
           markersURL = this.getClass().getResource(mfile);
           markers = new Markers(markersURL);
     /*
     ** Lets add our own marker to the marker list
           */
           int x[] = new int[12];
           int y[] = new int[12];
           boolean d[] = new boolean[12];
           x[0]=-2; y[0]= 4; d[0]=false;
           x[1]= 2; y[1]= 4; d[1]=true;
           x[2]= 0; y[2]= 4; d[2]=false;
           x[3]= 0; y[3]=-4; d[3]=true;
           x[4]=-2; y[4]=-4; d[4]=false;
           x[5]= 2; y[5]=-4; d[5]=true;
           x[6]=-4; y[6]= 0; d[6]=false;
           x[7]= 4; y[7]= 0; d[7]=true;
           x[8]=-4; y[8]= 2; d[8]=false;
           x[9]=-4; y[9]=-2; d[9]=true;
           x[10]=4; y[10]= 2; d[10]=false;
           x[11]=4; y[11]=-2; d[11]=true;
           markers.AddMarker(9,12,d,x,y);
        } catch(Exception e) {
            e.printStackTrace();
           System.out.println("Failed to create Marker URL!");
        }
        
 
        graph1.setMarkers(markers);
        graph2.setMarkers(markers);
        panel = new Panel();
        panel.setLayout( new GridLayout(0,2,0,0) );
        panel.add(graph1);
        panel.add(graph2);
        this.setLayout( new BorderLayout() );
        this.add("North", title);
        this.add("Center", panel);

/*
**      Calculate the first data Set.
*/
        for(i=j=0; i<np; i++,j+=2) {
            data[j] = j-np;
            data[j+1] = 60000 * Math.pow( ((double)data[j]/(np-2) ), 2);
        }
        data1 = graph1.loadDataSet(data,np);
        data1.linecolor   =  Color.red;
        data1.linestyle = 1;
        data1.marker    = 9;
        data1.markerscale = 1.0;
        data1.markercolor = new Color(0,0,255);
        data1.legend(150,75,"y=6x10{^4}x^2");
        data1.legendColor(Color.black);
/*
**      Calculate the Second data Set.
*/
        for(i=j=0; i<np; i++,j+=2) {
            data[j] = j-np;
            data[j+1] = Math.pow( ((double)data[j]/(np-2) ), 3);
        }
        data2 = graph2.loadDataSet(data, np);
        data2.linecolor   =  new Color(0,255,0);
        data2.marker      = 3;
        data2.markercolor = new Color(100,100,255);
        data2.legend(100,75,"y=x^3");
        data2.legendColor(Color.black);
/*
**      Attach data sets to the Xaxes
*/
        xaxis1 = graph1.createAxis(Axis.BOTTOM);
        xaxis1.attachDataSet(data1);
        xaxis1.setTitleText("Xaxis Left");
        xaxis1.setTitleFont(new Font("TimesRoman",Font.PLAIN,20));
        xaxis1.setLabelFont(new Font("Helvetica",Font.PLAIN,15));
        xaxis2 = graph2.createAxis(Axis.BOTTOM);
        xaxis2.attachDataSet(data2);
        xaxis2.setTitleText("Xaxis Right");
        xaxis2.setTitleFont(new Font("TimesRoman",Font.PLAIN,20));
        xaxis2.setLabelFont(new Font("Helvetica",Font.PLAIN,15));
/*
**      Attach the first data set to the Left Axis
*/
        yaxis1 = graph1.createAxis(Axis.LEFT);
        yaxis1.attachDataSet(data1);
        yaxis1.setTitleText("y=6x10{^4}x^2");
        yaxis1.setTitleFont(new Font("TimesRoman",Font.PLAIN,20));
        yaxis1.setLabelFont(new Font("Helvetica",Font.PLAIN,15));
        yaxis1.setTitleColor( new Color(0,0,255) );
        yaxis1.setTitleRotation(0);
/*
**      Attach the second data set to the Right Axis
*/
        yaxis2 = graph2.createAxis(Axis.RIGHT);
        yaxis2.attachDataSet(data2);
        yaxis2.setTitleText("y=x^3");
        yaxis2.setTitleFont(new Font("TimesRoman",Font.PLAIN,20));
        yaxis2.setLabelFont(new Font("Helvetica",Font.PLAIN,15));
        yaxis2.setTitleColor(new Color(100,100,255) );
        yaxis2.setTitleRotation(0);
      }
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         Applet app = new example1a();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }
}





Math function graph 1

/*************************************************************************
*                                                                        *
*  This source code file, and compiled classes derived from it, can      *
*  be used and distributed without restriction, including for commercial *
*  use.  (Attribution is not required but is appreciated.)               * 
*                                                                        *
*   David J. Eck                                                         *
*   Department of Mathematics and Computer Science                       *
*   Hobart and William Smith Colleges                                    *
*   Geneva, New York 14456,   USA                                        *
*   Email: eck@hws.edu          WWW: http://math.hws.edu/eck/            *
*                                                                        *
*************************************************************************/

import java.awt.*;
import edu.hws.jcm.data.*;
import edu.hws.jcm.draw.*;
import edu.hws.jcm.awt.*;
public class GraphApplet3 extends java.applet.Applet {
      public static void main(String[] a){
         javax.swing.JFrame f = new javax.swing.JFrame();
         java.applet.Applet app = new GraphApplet3();
         app.init();
         
         f.getContentPane().add (app);
         f.pack();
         f.setSize (new Dimension (500, 500));
         f.setVisible(true);
      }  
   private DisplayCanvas canvas;
   
   public void stop() {
      canvas.releaseResources();
   }
   
   public void init() {
   
      Parser parser = new Parser();
      Variable x = new Variable("x");
      parser.add(x);
      canvas = new DisplayCanvas();
      canvas.setHandleMouseZooms(true);
      canvas.add(new Panner());
      
      CoordinateRect coords = canvas.getCoordinateRect();
      
      LimitControlPanel limits =
           new LimitControlPanel( LimitControlPanel.SET_LIMITS | LimitControlPanel.RESTORE, false);
      limits.addCoords(canvas);
      
      ExpressionInput input = new ExpressionInput("sin(x)+2*cos(3*x)", parser);
      Function func = input.getFunction(x);
   
      Graph1D graph = new Graph1D(func);
      
      VariableInput xInput = new VariableInput();
      VariableSlider xSlider = new VariableSlider( coords.getValueObject(CoordinateRect.XMIN), 
                                                      coords.getValueObject(CoordinateRect.XMAX) );
      
      Value yValue = new ValueMath(func,xSlider); // A Value object to represent the y-coord of the point.
      
         // Instead of using a crosshair to mark a point on the graph, it is marked
         //   with two gray lines and a small magenta oval.  These geometric objects
         //   are represented as objects belonging to the class DrawGeometric,
         //   which makes it possible to draw a variety of geometric figures on a
         //   DisplayCanvas.
      DrawGeometric vLine = new DrawGeometric(DrawGeometric.LINE_ABSOLUTE,xSlider,new Constant(0),xSlider,yValue);
      DrawGeometric hLine = new DrawGeometric(DrawGeometric.LINE_ABSOLUTE,new Constant(0),yValue,xSlider,yValue);
      DrawGeometric point = new DrawGeometric(DrawGeometric.OVAL_CENTERED,xSlider,yValue,3,3);
      vLine.setColor(Color.lightGray);
      hLine.setColor(Color.lightGray);
      point.setColor(Color.magenta);
      point.setFillColor(Color.magenta);
      
      DrawString info = new DrawString("x = #\nf(x) = #", DrawString.TOP_LEFT,
                                                             new Value[] { xSlider, yValue });
      info.setFont( new Font("SansSerif",Font.BOLD,12) );
      info.setColor( new Color(0,100,0) );
      info.setOffset(10);
      ComputeButton graphIt = new ComputeButton("Graph It!");
      
      setLayout(new BorderLayout(3,3));
      setBackground(Color.lightGray);      
          // In this version of the applet, I have built the interface from
          //    regular Panels instead of JCMPanels.  This puts responsibility
          //    for a lot more setup in the hands of the programmer.  The gain
          //    is in efficiency.  Here, my object is to avoid recomputing the
          //    graph just because the user adjusts the slider.  To do this,
          //    I have to use two controllers, which listen for different user
          //    actions.  (Of course, computers are so fast now that the extra
          //    computation probably doesn"t add a perceptible delay.  In this 
          //    case, the extra design work is probably not worth the trouble.)
      Panel top = new Panel();
      top.setLayout(new BorderLayout(3,3));
      Panel bottom = new Panel();
      bottom.setLayout(new BorderLayout(3,3));
      add(canvas, BorderLayout.CENTER);  // Add components directly to the applet.
      add(limits, BorderLayout.EAST);
      add(bottom, BorderLayout.SOUTH);
      add(top, BorderLayout.NORTH);
      top.add(input, BorderLayout.CENTER);
      top.add(new Label(" f(x) = "), BorderLayout.WEST);
      top.add(graphIt, BorderLayout.EAST);
      
      bottom.add(xSlider, BorderLayout.CENTER);
      bottom.add(xInput, BorderLayout.EAST);
      bottom.add(new Label("  x = "), BorderLayout.WEST);
      
      canvas.add( new Axes() );
      canvas.add( hLine );
      canvas.add( vLine );
      canvas.add( point );
      canvas.add( graph );
      canvas.add( info );
      canvas.add( new DrawBorder(Color.darkGray, 2) );
      
      Controller cc = new Controller();  // This controller will listen for changes
      xInput.setOnUserAction(cc);        //   In the VariableSlider or VariableInput,
      xSlider.setOnUserAction(cc);       //   As well as in the limits on the coordinates.
      coords.setOnChange(cc);
      cc.add( new Tie(xSlider,xInput) ); // Ties the values of the slider and VariableInput.
      
      cc.add( hLine );    // I have to tell the controller which objects need to be recomputed
      cc.add( vLine );    //    when it sees some kind of change.  This includes all the 
      cc.add( point );    //    objects that depend on the x-coordinate.  Note that is ALSO
      cc.add( info );     //    includes xInput and xSlider, which need to be checked for 
      cc.add( xInput );   //    changes in their values.  The value associated with a
      cc.add( xSlider );  //    VariableSlider or VariableInput doesn"t actually change
                          //    until a Controller checks it.  (All this is the part of the
                          //    setup that is done automatically when you build your
                          //    interface from JCMPanels.)
      
      Controller gc = new Controller();   // This controller will listen for changes
      input.setOnUserAction(gc);          //   in the function definition.
      graphIt.setOnUserAction(gc);
      
      gc.add(input);   // I have to add the ExpressionInput to a Controller, since the
                       //   function doesn"t actually change unless the ExpressionInput
                       //   is checked by a Controller.
      gc.add(graph);   // The graph needs to be recomputed when the function changes.
      gc.add(cc);      // You can add one Controller to another.  Here, gc will call
                       //   on cc to do all its checks and computations, in addition to.
                       //   recomputing the graph.
      
      gc.setErrorReporter(canvas);      // Set error reporters for the Controller.
                                        //   This error reporter is also used by
                                        //   cc, which has been added as a subcontroller
                                        //   to gc.  So, it"s not necessary to set a separate
                                        //   error reporter for cc
      limits.setErrorReporter(canvas);  // Error reporter for the LimitControlPanel.
      
   } // end init()
} // end class SimpleGraph3





Science Parser

import java.awt.*;
import java.applet.*;
import graph.*;
public class parser extends Applet {

    public static void main( String arg[] ) {
        int l = arg.length;
        double d;
        if( l < 1 || l > 4 ) {
          System.out.println(
           "Usage: java parser \"function\" [x value] [y value] [z value]");
          return;
        }
        System.out.println("Parse Function: "+arg[0]);
        ParseFunction function = new ParseFunction(arg[0]);

        if( l >= 2 ) {
                      d = Double.valueOf(arg[1]).doubleValue();
                      System.out.println("x = "+d);
                      function.setX(d);
        }
        if( l >= 3 ) {
                      d = Double.valueOf(arg[2]).doubleValue();
                      System.out.println("y = "+d);
                      function.setY(d);
        }
        if( l >= 4 ) {
                      d = Double.valueOf(arg[3]).doubleValue();
                      System.out.println("z = "+d);
                      function.setZ(d);
        }
        function.debug = true;
        if( !function.parse() ) {
          System.out.println("Error: Failed to parse function");
          return;
        }
        try {
             System.out.println("Solution: "+function.getResult());
        } catch(Exception e) {
             e.printStackTrace();
        }
    }

}