Mega Code Archive

 
Categories / Java / Advanced Graphics
 

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.compute();       }       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.compute();       }    } // 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.compute();       }       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.compute();       }       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.compute();           } // 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                     jcm1-source.zip( 532 k)