Function Composition : Math Functions « Advanced Graphics « Java

Java
1. 2D Graphics GUI
2. 3D
3. Advanced Graphics
4. Ant
5. Apache Common
6. Chart
7. Collections Data Structure
8. Database SQL JDBC
9. Design Pattern
10. Development Class
11. Email
12. Event
13. File Input Output
14. Game
15. Hibernate
16. J2EE
17. J2ME
18. JDK 6
19. JSP
20. JSTL
21. Language Basics
22. Network Protocol
23. PDF RTF
24. Regular Expressions
25. Security
26. Servlets
27. Spring
28. Swing Components
29. Swing JFC
30. SWT JFace Eclipse
31. Threads
32. Tiny Application
33. Velocity
34. Web Services SOA
35. XML
Microsoft Office Word 2007 Tutorial
Java Tutorial
Java Source Code / Java Documentation
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
C# / C Sharp
C# / CSharp Tutorial
ASP.Net
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
PHP
Python
SQL Server / T-SQL
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Java » Advanced Graphics » Math FunctionsScreenshots 
Function Composition
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[] { 606306 };
      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 == || gap[0|| gap[050)
         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[] { -55, -,};
   
      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])01.0/3.001,null);
      canvas.addCoordinateRect(new CoordinateRect(limits[0],limits[1],limits[2],limits[3]),1.0/3.02.0/3.00,1,null);
      canvas.addCoordinateRect(new CoordinateRect(limits[0],limits[1],limits[2],limits[3]),2.0/3.0101null);
      
      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 SimpleFunctionparser.parse(fSaveText), xVar );
         gFunc = new SimpleFunctionparser.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, -55);
      }
      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, -55);
      }
      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 DrawGeometricDrawGeometric.LINE_ABSOLUTE, pointX, new Constant(0), pointX, fOfX );
      line1.setColor(pointColor1);
      canvas.add(line1, 0);
      
      DrawGeometric line2;
      line2 = new DrawGeometricDrawGeometric.LINE_ABSOLUTE, pointX, fOfX, new Constant(0), fOfX );
      line2.setColor(pointColor2);
      canvas.add(line2, 0);
      
      DrawGeometric line3;
      line3 = new DrawGeometricDrawGeometric.LINE_ABSOLUTE, fOfX, new Constant(0), fOfX, gOfFOfX );
      line3.setColor(pointColor2);
      canvas.add(line3, 1);
      
      DrawGeometric line4;
      line4 = new DrawGeometricDrawGeometric.LINE_ABSOLUTE, fOfX, gOfFOfX, new Constant(0), gOfFOfX );
      line4.setColor(pointColor3);
      canvas.add(line4, 1);
      
      DrawGeometric line5;
      line5 = new DrawGeometricDrawGeometric.LINE_ABSOLUTE, pointX, new Constant(0), pointX, gOfFOfX );
      line5.setColor(pointColor1);
      canvas.add(line5, 2);
      
      DrawGeometric line6;
      line6 = new DrawGeometricDrawGeometric.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 == || bw[025)
         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);
          
&nbs